home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 001a / mskrmsrc.zip / MSSSER.ASM < prev    next >
Assembly Source File  |  1991-10-24  |  70KB  |  2,234 lines

  1.     NAME    mssser
  2. ; File MSSSER.ASM
  3.     include mssdef.h
  4. ;       Copyright (C) 1982,1991, Trustees of Columbia University in the
  5. ;       City of New York.  Permission is granted to any individual or
  6. ;       institution to use, copy, or redistribute this software as long as
  7. ;       it is not sold for profit and this copyright notice is retained.
  8. ; Edit history:
  9. ; 6 Sept 1991 version 3.11
  10. ; Last edit 27 Aug 1991
  11.  
  12.     public    logout, bye, finish, remote, get, server, denyflg, srvtmo
  13.     public    luser, lpass
  14.  
  15. data    segment
  16.     extrn    flags:byte, trans:byte, curdsk:byte, diskio:byte, auxfile:byte
  17.     extrn    comand:byte, filtst:byte, maxtry:byte, dtrans:byte
  18.     extrn    fmtdsp:byte, errlev:byte, fsta:word, kstatus:word
  19.     extrn    rpacket:byte, encbuf:byte, decbuf:byte, sstate:byte
  20.     extrn    rstate:byte, pktnum:byte, windlow:byte, takadr:word
  21.     extrn    prmptr:word, chkparflg:byte
  22.  
  23. scrser    equ    0209H        ; place for server state display line
  24. scrmsg    equ    0C16H        ; place for Last message
  25.  
  26. remcmd    db    0        ; Remote command to be executed
  27. rempac    db    0        ; Packet type: C (host) or G (generic)
  28. remlen    db    0        ; length of following text field
  29.  
  30. ermes6    db    'Filename too long for packet',0
  31. cemsg    db    'User intervention',0
  32. infms1    db    'Server mode: type C or Control-C to exit',cr,lf,'$'
  33. infms2    db    cr,lf,'?More parameters are needed$'
  34. infms3    db    'REMOTE command reply',0    ; for transaction logging
  35. infms4    db    'Help text',0            ; filename for REM Help reply
  36. inthlp    db    cr,lf,' Time-limit to remain in Server mode, seconds or'
  37.     db    ' specific hh:mm:ss (24h clock).'
  38.     db    cr,lf,' SET TIMER ON to time.  Return for no time limit.$'
  39. remms1    db    ' Unknown server command',0
  40. remms2    db    ' Invalid login information',0
  41. remms3    db    ' Kermit-MS Server ready',0
  42. remms5    db    ' File not found',0
  43. remms6    db    ' Command failed',0
  44. remms7    db    ' REMOTE LOGIN is required',0
  45. remms8    db    ' Command succeeded',0
  46. remms9    db    ' Command is Disabled',0
  47. remms10    db    ' Could not create work file',0
  48. byemsg    db    ' Goodbye!',0
  49. whomsg    db    ' Just this Server',0
  50. spcmsg    db    ' bytes available on drive '    ; remote space responses
  51. spcmsg1    db    ' ',0
  52. spcmsg2    db    ' Drive '
  53. spcmsg3    db    ' : is not ready',0
  54. user    db    ' Username: ',0        ; for Remote Login, asciiz
  55. password db    ' Password: ',0        ; for Remote Login and Remote CD
  56. account    db    ' Account: ',0        ; for Remote Login
  57. slogin    db    0            ; non-zero if successful local login
  58. luser    db    17 dup (0)        ; local Username, case insenstitive
  59. lpass    db    17 dup (0)        ; local Password, case sensitive
  60. srvtmp    db    ' > :$kermit$.tmp',0    ; asciiz, kermit's temp output file
  61. delstr    db    'del ',0
  62. dirstr    db    'dir ',0
  63. crlf    db    cr,lf,'$'
  64. emptymsg db    0            ; empty asciiz msg
  65. skertmp    dw    0            ; REMOTE KERMIT work word
  66. denyflg    dw    0            ; bit field of denied commands
  67. temp    dw    0
  68. temp2    dw    0
  69. cnt    dw    0
  70. bufptr    dw    0
  71. dsptmp    db    0            ; temp to hold fmtdsp during serving
  72. srvtmo    db    0            ; idle NAK time, default is no NAKs
  73. srvtime    db    0            ; non-zero if timing Server residence
  74. remfnm    db    ' Remote Source File: ',0    ; asciiz
  75. lclfnm    db    ' Local Destination File: ',0    ; asciiz
  76. filhlp    db    ' File name to use locally$'
  77. filmsg    db    ' Remote filename, or press ENTER for prompts$'
  78. frem    db    ' Name of file on remote system $'
  79. genmsg    db    ' Enter text to be sent to remote server $'
  80. numhlp    db    ' number$'
  81. xfrhlp    db    ' character set identifier string$'
  82. tmpbuf    db    20 dup (0)
  83. srvbuf    db    80 dup (0)        ; place After tmpbuf, for status
  84.  
  85. savflg    flginfo    <>            ; save area for flags.*
  86. savflgl    equ    $-savflg        ; length
  87. savdtr    trinfo <>            ; save area for dtrans.*
  88. savdtrl equ    $-savdtr        ; length
  89. savtr    trinfo    <>            ; save area for trans.*
  90. savmaxtry db    0            ; save area for maxtry
  91.  
  92. srvchr    db    'SRGIECK'        ; server cmd characters, use w/srvfun
  93. srvfln    equ    $-srvchr        ; length of table
  94.  
  95. srvfun    dw    srvsnd,srvrcv,srvgen,srvini,srverr,srvhos,srvker ; for srvchr
  96.  
  97. srvch2    db    'CDEFHLMSTUW'        ; server commands, use with srvdsp
  98. srvfl2    equ    $-srvch2
  99.  
  100. srvdsp    dw    srvcwd,srvdir,srvdel,srvfin,srvhlp,srvlog,srvmsg
  101.     dw    srvset,srvtyp,srvspc,srvwho
  102.  
  103. remhlp    db    cr,lf,' Command    Action performed by the server Kermit'
  104.     db    cr,lf,' -------    -------------------------------------'
  105.     db    cr,lf,' CD/CWD     change working directory'    ; Answer to
  106.     db    cr,lf,' Delete     a file'            ; local
  107.     db    cr,lf,' Directory  filespec'            ; REM HELP
  108.     db    cr,lf,' Help       show server''s remote help screen'
  109.     db    cr,lf,' Host       command  (to remote operating system)'
  110.     db    cr,lf,' Kermit     command  (to Kermit server)'
  111.     db    cr,lf,' Login      name password  to a Kermit server'
  112.     db    cr,lf,' Message    short one line message'
  113.     db    cr,lf,' Print      local file  (on server''s printer)'
  114.     db    cr,lf,' Set        command  (modify server)'
  115.     db    cr,lf,' Space      drive/directory'
  116.     db    cr,lf,' Type       a file on this screen'
  117.     db    cr,lf,' Who        user parameters$'
  118.  
  119.                     ; Answer from Server to REMOTE HELP
  120. hlprem    db    cr,lf,'Kermit-MS Server commands:',lf
  121.     db    cr,lf,'GET  filespec            '
  122.     db    'REMOTE DIRECTORY filespec  REMOTE PRINT filespec'
  123.     db    cr,lf,'SEND filespec            '
  124.     db    'REMOTE HELP  this text     REMOTE SET command'
  125.     db    cr,lf,'FINISH, LOGOUT, BYE      '
  126.     db    'REMOTE HOST command        REMOTE SPACE drive-letter'
  127.     db    cr,lf,'REMOTE CD/CWD directory  '
  128.     db    'REMOTE LOGIN name password REMOTE TYPE filespec'
  129.     db    cr,lf,'REMOTE DELETE filespec   '
  130.     db    'REMOTE MESSAGE 1-line msg  REMOTE WHO'
  131.     db    0
  132.  
  133. remtab    db    14            ; 14 entries
  134.     mkeyw    'CD',remcwd
  135.     mkeyw    'CWD',remcwd
  136.     mkeyw    'Delete',remdel
  137.     mkeyw    'Directory',remdir
  138.     mkeyw    'Help',remhel
  139.     mkeyw    'Host',remhos
  140.     mkeyw    'Kermit',remker
  141.     mkeyw    'Login',remlogin
  142.     mkeyw    'Message',remmsg
  143.     mkeyw    'Print',remprn        ; top of SEND procedure in msssen
  144.     mkeyw    'Set',remset
  145.     mkeyw    'Space',remdis
  146.     mkeyw    'Type',remtyp
  147.     mkeyw    'Who',remwho
  148.  
  149. setval    dw    300,302,310            ; answer REMOTE SET workers
  150.     dw    400,401,402,403,404,405,406
  151. setvlen    equ    ($-setval)/2            ; number of entries
  152. setvec    dw    sftype,sfcoll,sfinc        ; routines paralleling setval
  153.     dw    sblkck,srpkt,srtmo,sretry,sstmo,sxfrch,swind
  154.  
  155. remstt1    db    9            ; REMOTE SET top level table
  156.     mkeyw    'Attributes',1
  157.     mkeyw    'File',2
  158.     mkeyw    'Incomplete',310
  159.     mkeyw    'Block-check',400
  160.     mkeyw    'Receive',3
  161.     mkeyw    'Retry',403
  162.     mkeyw    'Server',404
  163.     mkeyw    'Transfer',405
  164.     mkeyw    'Window-slots',406
  165.  
  166. remsat1    db    2            ; REMOTE SET ATTRIBUTES
  167.     mkeyw    'IN',0
  168.     mkeyw    'OUT',100
  169.  
  170. remsat2    db    17            ; REMOTE ATTRIBUTES {IN} item
  171.                     ; REM ATT {OUT} item is 100 greater
  172.     mkeyw    'All',132
  173.     mkeyw    'Length',133
  174.     mkeyw    'Type',134
  175.     mkeyw    'Date',135
  176.     mkeyw    'Creator',136
  177.     mkeyw    'Account',137
  178.     mkeyw    'Area',138
  179.     mkeyw    'Block-size',139
  180.     mkeyw    'Access',140
  181.     mkeyw    'Encoding',141
  182.     mkeyw    'Disposition',142
  183.     mkeyw    'Protection',143
  184.     mkeyw    'Gprotection',144
  185.     mkeyw    'System-ID',145
  186.     mkeyw    'Format',146
  187.     mkeyw    'Sys-Info',147
  188.     mkeyw    'Byte-count',148
  189.  
  190. remsfit    db    5            ; REMOTE SET FILE
  191.     mkeyw    'Type',300
  192.     mkeyw    'Names',301
  193.     mkeyw    'Collision',302
  194.     mkeyw    'Replace',303
  195.     mkeyw    'Incomplete',310
  196.  
  197. remsfty    db    2            ; REMOTE SET FILE TYPE
  198.     mkeyw    'Text',0
  199.     mkeyw    'Binary',1
  200.  
  201. remsfna    db    2            ; REMOTE SET FILE NAME
  202.     mkeyw    'Converted',0
  203.     mkeyw    'Literal',1
  204.  
  205. remsfco    db    7            ; REMOTE SET FILE COLLISION
  206.     mkeyw    'Append',3
  207.     mkeyw    'Ask',5
  208.     mkeyw    'Backup',2
  209.     mkeyw    'Discard',4
  210.     mkeyw    'Rename',0
  211.     mkeyw    'Replace',1
  212.     mkeyw    'Update',6
  213.  
  214. remsfre    db    2            ; REMOTE SET FILE REPLACE
  215.     mkeyw    'Preserve',0
  216.     mkeyw    'Default',1
  217.  
  218. remsfin    db    2            ; REMOTE SET FILE INCOMPLETE
  219.     mkeyw    'Discard',0
  220.     mkeyw    'Keep',1
  221.  
  222. remsrcv    db    2            ; REMOTE SET RECEIVE
  223.     mkeyw    'Packet-length',401
  224.     mkeyw    'Timeout',402
  225.  
  226. remsxfr    db    1            ; REMOTE SET TRANSFER
  227.     mkeyw    'Character-set',405
  228.  
  229.  
  230. onoff    db    2            ; ON, OFF table
  231.     mkeyw    'off',0
  232.     mkeyw    'on',1
  233.  
  234. data    ends
  235.  
  236. code1    segment
  237.     extrn bufclr:far, pakptr:far, bufrel:far, makebuf:far, chkwind:far
  238.     extrn firstfree:far, getbuf:far, pakdup:far, rpack:far
  239. code1    ends
  240.  
  241. code    segment
  242.     extrn comnd:near, init:near, serini:near, rrinit:near
  243.     extrn read2:near, rpar:near, spar:near, intmsg:near, sparmax:near
  244.     extrn serhng:near, clrbuf:near, clearl:near
  245.     extrn dodec: near, doenc:near, packlen:near, send10:near, errpack:near
  246.     extrn pktsize:near, poscur:near, lnout:near, clrmod:near, ermsg:near
  247.     extrn rprpos:near, crun:near, prompt:near,  prtscr:near, strcat:near
  248.     extrn strlen:near, strcpy:near, fparse:near, isfile:near, ihostr:near
  249.     extrn begtim:near, inptim:near, chktmo:near, pcwait:near
  250.     extrn nakpak:near, sndpak:near, response:near
  251.     extrn msgmsg:near, ackpak:near, dskspace:near, cdsr:near, dec2di:near
  252.     extrn takopen:near, takclos:near, setcom:near
  253.     extrn remprn:near
  254.  
  255.     assume    cs:code, ds:data, es:nothing
  256.  
  257. ; Server command
  258.  
  259. SERVER    PROC    NEAR
  260.     mov    ah,cmword        ; get a word 
  261.     mov    dx,offset srvbuf    ; place to put text
  262.     mov    word ptr srvbuf,0    ; clear
  263.     mov    bx,offset inthlp    ; help message
  264.     call    comnd            ; get the pattern text
  265.     jnc    serv1a            ; nc = success
  266.     ret                ; failure
  267. serv1a:    mov    ah,cmeol
  268.     call    comnd
  269.     jnc    serv1b            ; nc = success
  270.     ret
  271. serv1b:    mov    srvtime,0        ; assume not doing timed residence
  272.     mov    si,offset srvbuf
  273.     mov    al,[si]
  274.     or    al,al            ; any time given?
  275.     jz    serv4            ; z = no
  276.     cmp    al,'0'            ; numeric or colon?
  277.     jb    serv2            ; b = not proper time value
  278.     cmp    al,':'            ; this covers the desired range
  279.     ja    serv2            ; a = no proper time value
  280.     call    inptim            ; convert text to timeout tod
  281.     jnc    serv3            ; c = syntax errors in time
  282. serv2:    stc                ; failure
  283.     ret
  284.  
  285. serv3:    mov    srvtime,1        ; say doing timed residence
  286. serv4:    or    flags.remflg,dserver    ; signify we are a server now
  287.     call    clrbuf            ; clear serial port buffer of junk
  288.     test    denyflg,pasflg        ; Login required?
  289.     jnz    serv4a            ; nz = no
  290.     or    denyflg,pasflg        ; assume no login info required
  291.     mov    al,luser        ; check for user/password required
  292.     or    al,lpass        ; if both null then no checks
  293.     jz    serv4a            ; z = null, no name/pass required
  294.     and    denyflg,not pasflg    ; say need name/password
  295. serv4a:    mov    dsptmp,0        ; assume no formatted server display
  296.     mov    al,dtrans.xchset    ; reset Transmission char set
  297.     mov    trans.xchset,al        ;  to the current user default
  298.     mov    al,dtrans.xtype        ; ditto for File Type
  299.     mov    trans.xtype,al
  300.     mov    si,offset flags        ; main flags structure
  301.     mov    di,offset savflg    ; save area
  302.     mov    cx,savflgl        ; length in bytes
  303.     push    es
  304.     push    ds
  305.     pop    es
  306.     cld
  307.     rep    movsb            ; save all of them
  308.     mov    si,offset dtrans    ; default transmission parameters
  309.     mov    di,offset savdtr    ; save area
  310.     mov    cx,savdtrl        ; length
  311.     rep    movsb            ; save all of them
  312.     mov    si,offset trans        ; active transmission paramters
  313.     mov    di,offset savtr        ; save area
  314.     mov    cx,savdtrl        ; same length
  315.     rep    movsb
  316.     mov    al,maxtry
  317.     mov    savmaxtry,al
  318.     pop    es
  319.     mov    si,offset rpacket    ; dummy packet
  320.     mov    rpacket.datlen,0    ; declare to be empty
  321.     call    spar            ; setup minimum operating conditions
  322.     test    flags.remflg,dquiet    ; quiet display?
  323.     jnz    serv9            ; nz = yes
  324.     mov    ah,prstr
  325.     mov    dx,offset crlf
  326.     int    dos
  327.     test    flags.remflg,dserial     ; serial display?
  328.     jnz    serv5            ; nz = yes
  329.     call    init            ; init formatted display
  330.     call    clrmod            ; but no modeline yet
  331.     mov    dl,fmtdsp
  332.     mov    dsptmp,dl        ; remember state of fmtdsp
  333.     mov    dx,scrser        ; move cursor near top of screen
  334.     call    poscur
  335. serv5:    mov    ah,prstr
  336.     mov    dx,offset infms1    ; say now in server mode
  337.     int    dos
  338.  
  339.                     ; TOP OF SERVER IDLE LOOP
  340. serv9:    test    flags.remflg,dquiet+dserial ; quiet or serial display?
  341.     jnz    serv10            ; nz = yes, do not change screen
  342.     mov    dx,scrmsg        ; move cursor to Last message area
  343.     add    dx,0100H    ; look at line below (DOS does CR/LF first)
  344.     call    poscur
  345.     call    clearl            ; and clear the line
  346.     mov    dl,cr            ; set cursor to left margin
  347.     mov    ah,conout
  348.     int    dos
  349. serv10:    xor    ax,ax
  350.     mov    flags.cxzflg,al        ; clear ^X, ^Z, ^C seen flag
  351.     mov    flags.xflg,al        ; reset X packet flag
  352.     mov    auxfile,al        ; say no override filename
  353.     mov    srvbuf,al        ; work buffer, clear
  354.     mov    al,dsptmp        ; get our fmtdsp state
  355.     mov    fmtdsp,al        ; and restore it
  356.     mov    trans.windo,1        ; but only 1 window slot here
  357.     call    makebuf            ; remake all buffers for new windowing
  358.     call    packlen            ; determine max packet length
  359.     mov    trans.chklen,1        ; checksum len = 1
  360.     mov    pktnum,0        ; pack number resets to 0
  361.     mov    al,srvtmo        ; use server mode timeout
  362.     or    al,al            ; is it zero?
  363.     jz    serv10b            ; z = yes, use regular timeout
  364.     mov    trans.stime,al        ; use this interval in the idle loop
  365. serv10b:call    serini            ; init serial line, just in case
  366.     jnc    serv11            ; nc = success
  367.     jmp    serv20            ; c = failure
  368. serv11:    cmp    srvtime,0        ; doing timed residence?
  369.     je    serv12            ; e = no
  370.     call    chktmo            ; check for time to exit Server mode
  371.     jnc    serv12            ; nc = ok
  372.     jmp    serv20            ; c = timeout, exit server mode
  373.  
  374. serv12:    mov    windlow,0        ; reset windowing
  375.     mov    pktnum,0        ; packet number to be used
  376.     call    getbuf            ; get a buffer
  377.     mov    chkparflg,1        ; check for unexpected parity
  378.     call    rpack            ; receive a packet, si has buffer ptr
  379.     mov    al,dtrans.stime        ; get default timeout interval
  380.     mov    trans.stime,al        ; restore active timeout interval
  381.     jc    serv13            ; c = timeout, bad pkt, intervention
  382.     mov    al,[si].seqnum        ; sequence number received
  383.     mov    rpacket.seqnum,al    ; for our reply
  384.     or    al,al            ; must be sequence number of zero
  385.     jnz    serv13            ; nz = bad packet
  386.     mov    ah,[si].pktype
  387.     cmp    ah,'I'            ; never "decode" S, I, and A packets
  388.     je    serv17            ; e = I packet
  389.     cmp    ah,'S'
  390.     je    serv17
  391.     cmp    ah,'A'
  392.     je    serv17
  393.     call     dodec            ; decode packet to decbuf
  394.     call    bufrel            ; release the packet buffer
  395.     jmp    short serv17        ; dispatch on packet type in ah
  396.  
  397. serv13:    cmp    flags.cxzflg,'C'     ; Control-C?
  398.     je    serv20            ; e = yes, exit server mode
  399.  
  400. serv14:    cmp    flags.cxzflg,'E'    ; ^E protocol abort?
  401.     jne    serv15            ; ne = no
  402.     call    bufclr            ; clear all buffers
  403.     mov    dx,offset cemsg    ; user intervention message for error packet
  404.     call    ermsg
  405.     mov    bx,dx
  406.     call    errpack            ; send error message
  407.     call    intmsg            ; show interrupt msg for Control-C-E
  408.     jmp    serv9
  409.  
  410. serv15:    cmp    [si].pktype,'T'        ; packet type of time-out?
  411.     jne    serv16            ; ne = no
  412.     cmp    srvtime,0        ; doing timed residence?
  413.     je    serv15a            ; e = no
  414.     call    chktmo            ; check for time to exit Server mode
  415.     jc    serv20            ; c = timeout, exit server mode
  416. serv15a:cmp    srvtmo,0        ; zero server pkt timeout?
  417.     je    serv16            ; e = yes, no NAKing
  418.     mov    rpacket.seqnum,0
  419.     call    nakpak            ; NAK the packet, uses rpacket
  420. serv16:    call    bufrel            ; release the buffer
  421.     jmp    serv9            ; to top of idle loop
  422.  
  423. serv17:    cmp    [si].pktype,'N'        ; received a NAK?
  424.     je    serv18            ; e = yes, ignore it
  425.     push    es
  426.     push    ds
  427.     pop    es            ; set es to data segment
  428.     mov    di,offset srvchr    ; server characters
  429.     mov    cx,srvfln        ; length of command set
  430.     mov    al,ah            ; packet type
  431.     cld
  432.     repne    scasb            ; hunt for it
  433.     pop    es
  434.     je    serv19            ; e = found that kind
  435.     mov    dx,offset remms1    ; say unknown server command
  436.     call    ermsg
  437.     mov    bx,dx
  438.     call    errpack            ; tell the other kermit
  439. serv18:    jmp    serv9            ; get another server command
  440.  
  441. serv19:    sub    di,offset srvchr+1    ; find offset, +1 for pre-increment
  442.     shl    di,1            ; convert to word index
  443.     call    srvfun[di]        ; call the appropriate handler
  444.     jc    serv20            ; c = someone wanted to exit
  445.     jmp    serv9            ; get another server command
  446.  
  447. serv20:    mov    di,offset flags        ; main flags structure
  448.     mov    si,offset savflg    ; save area
  449.     mov    cx,savflgl        ; length in bytes
  450.     push    es
  451.     push    ds
  452.     pop    es
  453.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  454.     mov    ah,flags.cxzflg        ; interruption flag
  455.     cld
  456.     rep    movsb            ; restore all of them
  457.     mov    di,offset dtrans    ; default transmission parameters
  458.     mov    si,offset savdtr    ; save area
  459.     mov    cx,savdtrl        ; length
  460.     rep    movsb            ; restore all of them
  461.     mov    di,offset trans        ; active transmission paramters
  462.     mov    si,offset savtr        ; save area
  463.     mov    cx,savdtrl        ; same length
  464.     rep    movsb
  465.     mov    flags.extflg,al        ; set flag as current
  466.     mov    flags.cxzflg,ah        ; restore interruption flag
  467.     mov    al,savmaxtry
  468.     mov    maxtry,al
  469.     pop    es
  470.     call    rprpos            ; put prompt here
  471.     and    flags.remflg,not dserver ; say not a server anymore
  472.     clc
  473.     ret
  474. SERVER    ENDP
  475.  
  476. ; commands executable while acting as a server
  477.  
  478. ; Validate LOGIN status. Return carry set if login is ok, else
  479. ; send Error Packet saying Login is required (but has not been done) and
  480. ; return carry clear. Carry bit is this way because returning to the server
  481. ; idle loop with carry set exits the server mode.
  482. logchk    proc    near
  483.     test    denyflg,pasflg        ; login required?
  484.     jnz    logchk1            ; nz = no (disabled)
  485.     cmp    slogin,0        ; logged in yet?
  486.     jne    logchk1            ; ne = yes
  487.     mov    dx,offset remms7    ; reply REMOTE LOGIN is required
  488.     call    ermsg
  489.     mov    bx,dx            ; errpack works from bx
  490.     mov    trans.chklen,1        ; reply with 1 char checksum
  491.     call    errpack
  492.     clc                ; say cannot proceed with command
  493.     ret
  494. logchk1:stc                ; say can proceed with command
  495.     ret
  496. logchk    endp
  497.  
  498. ; srvsnd - receives a file that a remote kermit is sending
  499. srvsnd    proc    near
  500.     call    logchk            ; check login status
  501.     jc    srvsnd1            ; c = ok
  502.     ret                ; else have sent error packet
  503. srvsnd1:call    init            ; setup display form
  504.     xor    ax,ax
  505.     test    denyflg,sndflg        ; command disabled?
  506.     jz    srvsnd2            ; z = no
  507.     mov    al,'.'            ; dot+nul forces use of current dir
  508. srvsnd2:mov    word ptr auxfile,ax    ; override name
  509.     mov    rstate,'R'        ; receive initiate state
  510.     jmp    read2            ; packet pointer is SI, still valid
  511. srvsnd    endp
  512.  
  513. ; srvrcv - send a file to a distant kermit
  514.  
  515. srvrcv    proc    near
  516.     call    logchk            ; check login status
  517.     jc    srrcv1            ; c = ok
  518.     ret                ; else have sent error packet
  519. srrcv1:    mov    si,offset decbuf    ; received filename, asciiz from dodec
  520.     test    denyflg,getsflg        ; command enabled?
  521.     jz    srrcv2            ; z = yes
  522.     mov    dx,si            ; source string, from other side
  523.     mov    di,offset srvbuf    ; local path
  524.     mov    si,offset tmpbuf    ; local filename
  525.     call    fparse            ; split string
  526. srrcv2:    mov    di,offset diskio.string    ; destination
  527.     call    strcpy            ; copy filename to diskio.string
  528.     mov    auxfile,0        ; no alias name
  529.     mov    sstate,'S'        ; set sending state
  530.     jmp    send10            ; this should send it
  531. srvrcv    endp
  532.  
  533. srverr    proc    near            ; incoming Error packet
  534.     clc                ; absorb and ignore
  535.     ret
  536. srverr    endp
  537.  
  538. ; srvgen - G generic server command dispatcher
  539. ;
  540. srvgen    proc    near
  541.     call    bufrel            ; release buffer
  542.     mov    al,decbuf        ; get first data character from pkt
  543.     cmp    al,'I'            ; LOGIN?
  544.     jne    srvge1            ; ne = no
  545.     jmp    srvlogin        ; yes
  546. srvge1:    call    logchk            ; check login status
  547.     jc    srvge2            ; c = ok
  548.     ret                ; else have sent error packet
  549. srvge2:    push    es
  550.     push    ds
  551.     pop    es            ; set es to data segment
  552.     mov    di,offset srvch2    ; command character list
  553.     mov    cx,srvfl2        ; length of command set
  554.     cld
  555.     repne    scasb            ; hunt for it
  556.     pop    es
  557.     jne    srvgex            ; ne = not found, complain
  558.     sub    di,offset srvch2+1    ; find offset, +1 for pre-increment
  559.     shl    di,1            ; convert to word index
  560.     jmp    srvdsp[di]        ; do the appropriate handler
  561.  
  562. srvgex:    mov    dx,offset remms1    ; reply Unknown server command
  563.     call    ermsg
  564.     mov    bx,dx
  565.     mov    trans.chklen,1        ; reply with 1 char checksum
  566.     call    errpack
  567.     clc
  568.     ret
  569. srvgen    endp
  570.  
  571. ; srvlog - respond to host's BYE and LOGOUT
  572. srvlog    proc    near
  573.     call    srvfin            ; do FIN part
  574.     pushf                ; save flag for the very end
  575.     jnc    srvlog1            ; nc = stay active (command denied)
  576.     mov    flags.extflg,1        ; leave server mode and Kermit
  577. srvlog1:call    serhng            ; hangup the phone and return
  578.     mov    di,offset flags        ; main flags structure
  579.     mov    si,offset savflg    ; save area
  580.     mov    cx,savflgl        ; length in bytes
  581.     push    es
  582.     push    ds
  583.     pop    es
  584.     mov    al,flags.extflg        ; leave server mode and Kermit flag
  585.     cld
  586.     rep    movsb            ; restore all of them
  587.     mov    di,offset dtrans    ; default transmission parameters
  588.     mov    si,offset savdtr    ; save area
  589.     mov    cx,savdtrl        ; length
  590.     rep    movsb            ; restore all of them
  591.     mov    di,offset trans        ; active transmission paramters
  592.     mov    si,offset savtr        ; save area
  593.     mov    cx,savdtrl        ; same length
  594.     rep    movsb
  595.     mov    flags.extflg,al        ; make flag current
  596.     mov    al,savmaxtry
  597.     mov    maxtry,al
  598.     pop    es
  599.     popf                ; recover carry flag, set = exit
  600.     ret
  601. srvlog    endp
  602.  
  603. ; srvfin - respond to remote host's Fin command
  604. srvfin    proc    near
  605.     mov    slogin,0        ; say not logged in anymore
  606.     mov    si,offset byemsg    ; add brief msg of goodbye
  607.     mov    di,offset encbuf    ; packet's data field
  608.     call    strcpy            ; copy msg to pkt
  609.     mov    dx,si            ; strlen works on dx
  610.     call    strlen
  611.     push    si
  612.     mov    si,offset rpacket    ; get a reply buffer
  613.     call    doenc            ; encode the reply in encbuf
  614.     pop    si
  615.     mov    trans.chklen,1        ; reply with 1 char checksum
  616.     call    ackpak
  617.     mov    ax,100            ; wait 0.1 sec for client to settle
  618.     call    pcwait
  619.     mov    si,offset rpacket    ; dummy packet
  620.     mov    rpacket.datlen,0    ; declare to be empty
  621.     call    spar            ; setup minimum operating conditions
  622.     test    denyflg,finflg        ; command enabled?
  623.     jz    srfin2            ; z = yes
  624.     clc                ; stay in server mode
  625.     ret
  626. srfin2:    stc                ; stc exits server mode
  627.     ret
  628. srvfin    endp
  629.  
  630. ; srvcwd - handle other side's Remote CWD dirspec
  631. srvcwd    proc    near
  632.     mov    trans.chklen,1        ; reply with 1 char checksum
  633.     test    denyflg,cwdflg        ; is command enabled?
  634.     jz    srcwd1            ; z = yes
  635.     mov    dx,offset remms9    ; say command is disabled
  636.     call    ermsg            ;  to us and
  637.     mov    bx,dx
  638.     call    errpack            ;  to the other Kermit
  639.     clc
  640.     ret
  641. srcwd1:    mov    si,offset decbuf+1    ; point to byte count
  642.     xor    bh,bh
  643.     mov    bl,[si]
  644.     sub    bl,' '            ; remove ascii bias from byte count
  645.     inc    si
  646.     mov    word ptr[si+bx],0    ; make ASCIIZ w/one extra null
  647.     call    cdsr            ; CD common sub-routine
  648.     mov    si,dx            ; returns msg in dx
  649.     mov    di,offset encbuf    ; put in encode buffer
  650.     call    strcpy
  651.     mov    dx,di
  652.     call    strlen            ; get its length to cx
  653.     mov    si,offset rpacket    ; use this packet for the reply
  654.     call    doenc            ; encode reply
  655.     call    ackpak            ; send ACK with data
  656.     clc
  657.     ret
  658. srvcwd    endp
  659.  
  660. ; srvtyp - handle other side's Remote Type filename request
  661. ; expects "data" to hold  Tcfilename   where c = # bytes in filename
  662. srvtyp    proc    near
  663.     cmp    decbuf+1,0        ; any data in packet
  664.     je    srtyp2            ; e = no
  665.     mov    cl,decbuf+1        ; get the filename byte count
  666.     sub    cl,' '            ; ascii to numeric
  667.     jle    srtyp2            ; le = no filename or error in length
  668.     xor    ch,ch            ; set up counter
  669.     mov    si,offset decbuf+2    ; received filename, asciiz from rpack
  670.     mov    di,si
  671.     add    di,cx
  672.     mov    byte ptr [di],0        ; make string asciiz
  673.     test    denyflg,typflg        ; paths permitted?
  674.     jz    srtyp1            ; z = yes, else use just filename part
  675.     mov    di,offset srvbuf    ; local path
  676.     mov    si,offset tmpbuf    ; local filename
  677.     mov    dx,offset decbuf+2    ; local string
  678.     call    fparse            ; split string
  679. srtyp1:    mov    di,offset diskio.string    ; copy local filename to destination
  680.     mov    ax,di            ; pointer to filename, for isfile
  681.     call    strcpy            ; do the copy
  682.     call    isfile            ; does it exist?
  683.     jnc    srtyp3            ; nc = yes
  684. srtyp2:    mov    si,offset remms5    ; "File not found"
  685.     mov    di,offset encbuf    ; destination for message
  686.     call    strcpy            ; move the message
  687.     mov    dx,di
  688.     call    strlen            ; length to cx
  689.     mov    si,offset rpacket    ; use this packet for reply
  690.     call    doenc            ; encode
  691.     mov    trans.chklen,1        ; reply with 1 char checksum
  692.     call    ackpak            ; send ACK with message
  693.     clc
  694.     ret
  695.  
  696. srtyp3:    mov    flags.xflg,1        ; say use X packet rather than F pkt
  697.     mov    auxfile,0        ; no alias name
  698.     mov    sstate,'S'        ; remember state
  699.     jmp    send10            ; this should send it
  700. srvtyp    endp
  701.  
  702. ; srvdir - handle other side's Remote Dir filespec(optional) request
  703. srvdir    proc    near
  704.     mov    di,offset decbuf+2      ; received filespec, asciiz from rpack
  705.     xor    cx,cx            ; assume no data in packet
  706.     mov    cl,decbuf+1        ; get the filename byte count
  707.     cmp    cl,' '            ; byte count present and > 0?
  708.     jg    srdir1            ; g = yes
  709.     mov    word ptr [di],0        ; clear data field
  710.     jmp    short srdir2        ; 0 = no info in pkt
  711. srdir1:    sub    cl,' '            ; ascii to numeric
  712.     add    di,cx            ; step to end of filename, terminate
  713.     mov    word ptr [di],0        ; ensure string is asciiz
  714.     mov    di,offset srvbuf    ; local path
  715.     mov    si,offset tmpbuf    ; local filename
  716.     mov    dx,offset decbuf+2    ; local string
  717.     call    fparse            ; split string
  718.     test    denyflg,dirflg        ; paths permitted?
  719.     jz    srdir2            ; z = yes, else use just filename part
  720.     mov    si,offset tmpbuf    ; copy local filename to
  721.     mov    di,offset decbuf+2    ; final filename
  722.     call    strcpy            ; copy just filename to buffer
  723. srdir2:    mov    cl,curdsk        ; current drive number
  724.     add    cl,'A'-1        ; to letter
  725.     cmp    decbuf+3,':'        ; drive specified?
  726.     jne    srdir3            ; ne = no
  727.     cmp    decbuf+2,0        ; drive letter specified?
  728.     je    srdir3            ; e = no
  729.     mov    cl,decbuf+2        ; get drive letter
  730.     and    cl,5fh            ; convert to upper case
  731. srdir3:    call    dskspace        ; check if drive ready (drive => CL)
  732.     jnc    srdir5            ; nc = success (drive is ready)
  733.     mov    spcmsg3,cl        ; insert drive letter
  734.     mov    si,offset spcmsg2    ; say drive not ready
  735.     mov    di,offset encbuf    ; destination for message
  736.     call    strcpy            ; move the message
  737.     mov    dx,di
  738.     call    strlen            ; length to cx
  739.     mov    si,offset rpacket    ; use this packet for reply
  740.     call    doenc            ; encode
  741.     mov    trans.chklen,1        ; reply with 1 char checksum
  742.     call    ackpak            ; send ACK with message
  743.     clc
  744.     ret
  745.  
  746. srdir5:    mov    di,offset srvbuf    ; work area
  747.     mov    si,offset dirstr    ; prepend "dir "
  748.     call    strcpy
  749.     mov    si,offset decbuf+2    ; directory spec, asciiz
  750.     mov    di,offset srvbuf
  751.     call    strcat
  752.  
  753. ; srdir6 does common processing for both REM DIR & REM HOST
  754. SRDIR6:    mov    si,di            ; srvbuf
  755.     mov    di,offset auxfile    ; send-as name is command line
  756.     call    strcpy
  757.     mov    dl,curdsk
  758.     add    dl,'A'-1        ; change to letter
  759.     mov    srvtmp+2,dl        ; insert current disk drive
  760.     mov    si,offset srvtmp    ; add redirection tag " >d:$kermit$.tmp"
  761.     mov    di,offset srvbuf
  762.     call    strcat
  763.     mov    si,offset srvbuf    ; command pointer for crun
  764.     call    crun
  765. ; fall thru!    jmp    srvtail            ; send contents of temp file
  766. srvdir    endp
  767.  
  768. ; Send contents of srvtmp+2 temporary file, or error packet if it does not
  769. ; exist.
  770. srvtail    proc    near
  771.     mov    si,offset srvtmp+2    ; get name of temp file
  772.     mov    di,offset diskio.string    ; destination
  773.     call    strcpy            ; copy it there
  774.     mov    ax,di            ; filename pointer for isfile
  775.     call    isfile            ; did we make the temp file?
  776.     jnc    srvtai1            ; nc = yes
  777.     mov    dx,offset remms10    ; "Could not create work file"
  778.     mov    trans.chklen,1        ; reply with 1 char checksum
  779.     call    ermsg
  780.     mov    bx,dx
  781.     call    errpack            ; send the error message
  782.     clc
  783.     ret
  784. srvtai1:mov    flags.xflg,1        ; say use X rather than F packet
  785.     mov    sstate,'S'        ; remember state
  786.     call    send10            ; this should send it
  787.     mov    flags.xflg,0        ; clear flag
  788.     mov    dx,offset srvtmp+2    ; name of temp file
  789.     mov    ah,del2            ; delete the file
  790.     int    dos
  791.     clc
  792.     ret                ; return in any case
  793. srvtail    endp
  794.  
  795. ; srvdel - handle other side's request of Remote Del filespec
  796. srvdel    proc    near
  797.     test    denyflg,delflg        ; command enabled?
  798.     jz    srvdel4            ; z = yes
  799.     mov    dx,offset remms9    ; else give a message
  800.     mov    trans.chklen,1        ; reply with 1 char checksum
  801.     call    ermsg
  802.     mov    bx,dx
  803.     call    errpack            ; back to local kermit
  804.     clc
  805.     ret
  806.  
  807. srvdel4:cmp    decbuf+1,0        ; any data?
  808.     je    srdel1            ; e = no
  809.     xor    bh,bh
  810.     mov    bl,decbuf+1        ; get the filename byte count
  811.     sub    bl,' '            ; ascii to numeric
  812.     jle    srdel3            ; le = nothing there
  813.     mov    decbuf [bx+2],0        ; plant terminator
  814.     mov    ax,offset decbuf+2    ; point to filespec
  815.     call     isfile            ; is/are there any to delete?
  816.     jc    srdel1            ; c = there is none
  817.     test    byte ptr filtst.dta+21,1EH ; attr bits: is file protected?
  818.     jz    srdel2            ; z = not protected
  819. srdel1:    mov    si,offset remms5    ; "File not found"
  820.     mov    di,offset encbuf    ; destination for message
  821.     call    strcpy            ; move the message
  822.     mov    dx,di
  823.     call    strlen            ; length to cx
  824.     mov    si,offset rpacket    ; use this packet for reply
  825.     call    doenc            ; encode
  826.     mov    trans.chklen,1        ; reply with 1 char checksum
  827.     call    ackpak            ; send ACK with message
  828.     clc
  829.     ret
  830.  
  831. srdel2:    mov    di,offset encbuf    ; work area
  832.     mov    si,offset delstr    ; prepend "del "
  833.     call    strcpy
  834.     mov    si,offset decbuf+2    ; append incoming filespec
  835.     call    strcat            ; append to "del "
  836.     mov    si,di            ; set pointer for crun
  837.     call    crun
  838. srdel3:    mov    dx,offset encbuf    ; where command lies
  839.     call    strlen            ; length to cx
  840.     push    si
  841.     mov    si,offset rpacket    ; packet to use for reply
  842.     call    doenc            ; encode reply
  843.     pop    si
  844.     mov    trans.chklen,1        ; reply with 1 char checksum
  845.     call    ackpak
  846.     clc
  847.     ret
  848. srvdel    endp
  849.  
  850. ; srvlogin - handle other side's request of REMOTE LOGIN, USERNAME, PASSWORD
  851.  
  852. srvlogin proc    near
  853.     mov    slogin,0        ; say not logged in yet
  854.     cmp    luser,0            ; local username specified?
  855.     je    srvlog9            ; e = no, do no checking
  856.     mov    cl,decbuf+1        ; ascii byte count of username
  857.     sub    cl,' '            ; to binary
  858.     jle    srvlog8            ; le = nothing there
  859.     xor    ch,ch
  860.     mov    si,offset decbuf+2    ; source, username field
  861.     mov    di,offset luser        ; local username template
  862.     push    cx
  863.     mov    ax,cx            ; external username length
  864.     mov    dx,di
  865.     call    strlen            ; get length of local username
  866.     cmp    ax,cx            ; same lengths?
  867.     pop    cx
  868.     jne    srvlog8            ; ne = not same length
  869.     cld
  870. srvlog2:lodsb                ; remote char
  871.     mov    ah,[di]            ; local char
  872.     inc    di
  873.     or    ax,2020h        ; lower case both
  874.     cmp    ah,al            ; same?
  875.     jne    srvlog8            ; ne = no, fail
  876.     loop    srvlog2            ; continue match
  877.     cmp    lpass,0            ; local password specified?
  878.     je    srclog6            ; e = no, don't check incoming p/w
  879.     mov    cl,decbuf+1        ; username length
  880.     sub    cl,' '
  881.     xor    ch,ch            ; clear high byte
  882.     mov    si,offset decbuf+2    ; skip over username field
  883.     add    si,cx            ; password length byte
  884.     mov    cl,[si]            ; ascii count of password bytes
  885.     sub    cl,' '            ; to binary
  886.     jc    srvlog8            ; carry means no field
  887.     inc    si            ; start of password text
  888.     mov    di,offset lpass        ; local password text, case sensitive
  889.     push    cx
  890.     mov    ax,cx            ; external password length
  891.     mov    dx,di
  892.     call    strlen            ; length of local password
  893.     cmp    ax,cx            ; same?
  894.     pop    cx
  895.     je    srvlog5            ; e = yes
  896.     mov    byte ptr [si],20h    ; corrupt external password
  897.     jmp    short srvlog8        ; fail
  898. srvlog5:lodsb                ; remote char
  899.     mov    ah,[di]            ; local char
  900.     inc    di
  901.     cmp    ah,al            ; same?
  902.     jne    srvlog8            ; ne = no, fail
  903.     loop    srvlog5            ; do all chars
  904. srclog6:mov    slogin,1        ; declare user logged-in
  905.     jmp    short srvlog9        ; ACK with brief message
  906.  
  907. srvlog8:mov    si,offset remms2    ; say invalid login information
  908.     jmp    short srvlog10
  909.  
  910. srvlog9:mov    si,offset remms3    ; welcome aboard message
  911.     mov    slogin,1        ; say logged in successfully
  912. srvlog10:mov    di,offset encbuf    ; copy to here
  913.     call    strcpy
  914.     mov    dx,di            ; where command lies
  915.     call    strlen            ; length to cx
  916.     push    si
  917.     mov    si,offset rpacket    ; packet to use for reply
  918.     call    doenc            ; encode reply
  919.     pop    si
  920.     mov    trans.chklen,1        ; reply with 1 char checksum
  921.     call    ackpak
  922.     clc
  923.     ret
  924. srvlogin endp
  925.  
  926. ; srvspc - handle other side's request of Remote Space
  927. srvspc    proc    near
  928.     test    denyflg,spcflg        ; is command enabled?
  929.     jz    srspc1            ; z = yes
  930.     mov    dx,offset remms9    ; else give a message
  931.     mov    trans.chklen,1        ; reply with 1 char checksum
  932.     call    ermsg
  933.     mov    bx,dx
  934.     call    errpack            ; back to local kermit
  935.     clc
  936.     ret
  937. srspc1:    xor    cl,cl            ; use current drive
  938.     cmp    decbuf+1,0        ; any data?
  939.     je    srspc2            ; e = no
  940.     mov    cl,decbuf+2        ; get the drive letter
  941. srspc2:    call    dskspace        ; calculate space, get letter into CL
  942.     jnc    srspc3            ; nc = success
  943.     mov    spcmsg3,cl        ; insert drive letter
  944.     mov    di,offset encbuf    ; encoder buffer
  945.     mov    si,offset spcmsg2    ; give Drive not ready message
  946.     call    strcpy
  947.     jmp    short srspc4        ; send it
  948. srspc3:    mov    spcmsg1,cl        ; insert drive letter
  949.     mov    di,offset encbuf    ; destination
  950.     mov    word ptr[di],'  '    ; space space
  951.     add    di,2            ; start number here
  952.     call    lnout            ; convert number to asciiz in [di]
  953.     mov    si,offset spcmsg    ; trailer of message
  954.     call    strcat            ; tack onto end of number part
  955. srspc4:    mov    trans.chklen,1        ; reply with 1 char checksum
  956.     mov    dx,offset encbuf
  957.     call    strlen            ; get data size into cx for doenc
  958.     mov    si,offset rpacket
  959.     call    doenc            ; encode
  960.     call    pktsize            ; report packet size
  961.     call    ackpak
  962.     clc
  963.     ret
  964. srvspc    endp
  965.  
  966. ; srvwho - respond to remote host's WHO command.
  967. srvwho    proc    near
  968.     mov    si,offset whomsg    ; add brief msg of just us chickens
  969.     mov    di,offset encbuf    ; encoder source field
  970.     call    strcpy            ; copy msg to pkt
  971.     mov    dx,si            ; strlen works on dx
  972.     call    strlen
  973.     mov    si,offset rpacket
  974.     call    doenc            ; encode reply, size is in cx
  975.     mov    trans.chklen,1        ; reply with 1 char checksum
  976.     call    ackpak
  977.     clc
  978.     ret
  979. srvwho    endp
  980.  
  981. ; srvmsg - respond to remote host's Message (Send) command
  982. ;  show message on our screen.
  983. srvmsg    proc    near
  984.     cmp    decbuf,0        ; any data in the packet?
  985.     jbe    srvmsg2            ; e = no, just ack the message 
  986.     cmp    decbuf,'M'        ; Message packet?
  987.     jne    srvmsg2            ; ne = no, ack and forget
  988.     test    flags.remflg,dquiet+dserial ; quiet or serial display?
  989.     jnz    srvmsg1            ; nz = yes
  990.     mov    dx,scrmsg        ; move cursor to Last message area
  991.     call    poscur
  992.     call    clearl            ; and clear the line
  993. srvmsg1:xor    ch,ch
  994.     mov    cl,decbuf+1        ; data length
  995.     sub    cl,' '            ; remove ascii bias
  996.     jle    srvmsg2            ; le = nothing
  997.     mov    di,offset decbuf+2    ; main part of message
  998.     call    prtscr            ; display cx chars on the screen
  999. srvmsg2:mov    rpacket.datlen,0    ; length
  1000.     mov    trans.chklen,1        ; reply with 1 char checksum
  1001.     call    ackpak
  1002.     clc
  1003.     ret
  1004. srvmsg    endp
  1005.  
  1006.  
  1007. ; srvhos - handle other side's request of REM Host command-line. [jrd]
  1008. ; We execute the command with STDOUT redirected to $kermit$.tmp and then
  1009. ; read and transmit that file to the other end. No such file results in
  1010. ; returning just an error msg ACK packet
  1011. srvhos    proc    near
  1012.     call    logchk            ; check login status
  1013.     jc    srvhos1            ; c = ok
  1014.     ret                ; else have sent error packet
  1015. srvhos1:test    denyflg,hostflg        ; command enabled?
  1016.     jz    srvhos2            ; z = yes
  1017.     mov    trans.chklen,1        ; reply with 1 char checksum
  1018.     mov    dx,offset remms9    ; else give a message
  1019.     call    ermsg
  1020.     mov    bx,dx
  1021.     call    errpack            ; back to local kermit
  1022.     clc
  1023.     ret
  1024.  
  1025. srvhos2:mov    si,offset decbuf    ; received filename, asciiz from dodec
  1026.     mov    di,offset srvbuf    ; destination
  1027.     call    strcpy            ; copy data to srvbuf
  1028.     jmp    SRDIR6            ; do common completion code
  1029. srvhos    endp
  1030.  
  1031. ; Respond to other side's request of Remote Help. Write & read $kermit$.tmp
  1032. srvhlp    proc    near
  1033.     mov    dl,curdsk
  1034.     add    dl,'A'-1        ; change to letter
  1035.     mov    srvtmp+2,dl        ; insert current disk drive
  1036.     mov    dx,offset srvtmp+2    ; use filename of d:$kermit$.tmp
  1037.     mov    ah,creat2        ; create the file
  1038.     xor    cx,cx            ; attributes r/w
  1039.     int    dos
  1040.     jc    srvhlp1            ; c = could not open
  1041.     mov    dx,offset hlprem    ; data to be sent, strlen uses dx
  1042.     call    strlen            ; put string length in cx
  1043.     mov    bx,ax            ; handle
  1044.     mov    ah,write2        ; write to file
  1045.     int    dos            ; write the info
  1046.     mov    ah,close2    ; close the file so we can reread it below
  1047.     int    dos
  1048. srvhlp1:mov    si,offset infms4    ; pseudo filename
  1049.     mov    di,offset auxfile    ; send-as name
  1050.     call    strcpy            ; copy it there
  1051.     jmp    srvtail            ; send temporary file to remote screen
  1052. srvhlp    endp
  1053.  
  1054. ; srvker - handle other side's request of REM Kermit command-line.
  1055. srvker    proc    near
  1056.     call    logchk            ; check login status
  1057.     jc    srvker8            ; c = ok
  1058.     ret                ; else have sent error packet
  1059. srvker8:test    denyflg,kerflg        ; command enabled?
  1060.     jz    srvker1            ; z = yes
  1061.     mov    trans.chklen,1        ; reply with 1 char checksum
  1062.     mov    dx,offset remms9    ; else give a message
  1063.     call    ermsg
  1064.     mov    bx,dx
  1065.     call    errpack            ; back to local kermit
  1066.     clc
  1067.     ret
  1068.  
  1069. srvker1:call    takopen            ; open a Take file
  1070.     jc    srvker3            ; c = failed to obtain Take space
  1071.     mov    dx,prmptr        ; get prompt
  1072.     call    prompt              ; prompt user, set reparse address
  1073.     mov    bx,takadr        ; pointer to Take structure
  1074.     mov    skertmp,bx        ; remember it here for cleanup
  1075.     mov    [bx].taktyp,0ffh    ; mark as a macro
  1076.     mov    dx,offset decbuf    ; received command, asciiz
  1077.     call    strlen            ; get length into cx
  1078.     mov    si,dx
  1079. srvker6:cmp    byte ptr [si],' '    ; strip leading white space
  1080.     ja    srvker7            ; a = non-white
  1081.     loop    srvker6            ; continue
  1082. srvker7:cmp    cx,8            ; need at least 8 chars "SET xx y"
  1083.     jb    srvker2            ; b = too few, bad command
  1084.     mov    ax,[si]            ; get first two characters
  1085.     or    ax,2020h        ; lower case them
  1086.     cmp    ax,'es'            ; start of "SET"?
  1087.     jne    srvker2            ; ne = no, bad command
  1088.     mov    ax,[si+2]        ; next two
  1089.     or    ax,2020h
  1090.     cmp    ax,' t'            ; rest of "SET "?
  1091.     jne    srvker2            ; ne = no, bad command
  1092.     add    si,4            ; move to end of "SET "
  1093.     sub    cx,4
  1094.     mov    [bx].takcnt,cx        ; number of bytes in command
  1095.     push    es
  1096.     mov    ax,[bx].takbuf        ; segment of Take buffer
  1097.     mov    es,ax
  1098.     mov    di,1            ; place here (skip buf length byte)
  1099.     cld
  1100.     rep    movsb
  1101.     pop    es
  1102.     call    setcom
  1103.     jnc    srvker3            ; nc = success
  1104. srvker2:mov    si,offset remms6    ; "Command failed"
  1105.     jmp    short srvker4
  1106. srvker3:mov    si,offset remms8    ; "Command succeeded"
  1107. srvker4:mov    di,offset encbuf    ; destination for message
  1108.     call    strcpy            ; move the message
  1109.     mov    dx,di
  1110.     call    strlen            ; length to cx
  1111.     mov    si,offset rpacket    ; use this packet for reply
  1112.     call    doenc            ; encode
  1113.     mov    trans.chklen,1        ; reply with 1 char checksum
  1114.     call    ackpak            ; send ACK with message
  1115.     mov    ax,skertmp        ; get old take address
  1116.     cmp    ax,takadr        ; same (still in current Take)?
  1117.     jne    srvker5            ; ne = no
  1118.     call    takclos            ; close the Take file
  1119. srvker5:clc
  1120.     ret
  1121. srvker    endp
  1122.  
  1123. ;  Command                                Code   Values
  1124. ;  REMOTE SET ATTRIBUTES IN ALL            132   0 = OFF, 1 = ON
  1125. ;  REMOTE SET ATTRIBUTES IN LENGTH         133   0 = OFF, 1 = ON
  1126. ;  REMOTE SET ATTRIBUTES IN TYPE           134   0 = OFF, 1 = ON
  1127. ;  REMOTE SET ATTRIBUTES IN DATE           135   0 = OFF, 1 = ON
  1128. ;X  REMOTE SET ATTRIBUTES IN CREATOR        136   0 = OFF, 1 = ON
  1129. ;X  REMOTE SET ATTRIBUTES IN ACCOUNT        137   0 = OFF, 1 = ON
  1130. ;X  REMOTE SET ATTRIBUTES IN AREA           138   0 = OFF, 1 = ON
  1131. ;X  REMOTE SET ATTRIBUTES IN BLOCK-SIZE     139   0 = OFF, 1 = ON
  1132. ;X  REMOTE SET ATTRIBUTES IN ACCESS         140   0 = OFF, 1 = ON
  1133. ;X  REMOTE SET ATTRIBUTES IN ENCODING       141   0 = OFF, 1 = ON
  1134. ;X  REMOTE SET ATTRIBUTES IN DISPOSITION    142   0 = OFF, 1 = ON
  1135. ;X  REMOTE SET ATTRIBUTES IN PROTECTION     143   0 = OFF, 1 = ON
  1136. ;X  REMOTE SET ATTRIBUTES IN GPROTECTION    144   0 = OFF, 1 = ON
  1137. ;X  REMOTE SET ATTRIBUTES IN SYSTEM-ID      145   0 = OFF, 1 = ON
  1138. ;X  REMOTE SET ATTRIBUTES IN FORMAT         146   0 = OFF, 1 = ON
  1139. ;X  REMOTE SET ATTRIBUTES IN SYS-INFO       147   0 = OFF, 1 = ON
  1140. ;X  REMOTE SET ATTRIBUTES IN BYTE-COUNT     148   0 = OFF, 1 = ON
  1141. ;
  1142. ;  REMOTE SET ATTRIBUTES OUT ALL           232   0 = OFF, 1 = ON
  1143. ;  REMOTE SET ATTRIBUTES OUT LENGTH        233   0 = OFF, 1 = ON
  1144. ;  REMOTE SET ATTRIBUTES OUT TYPE          234   0 = OFF, 1 = ON
  1145. ;  REMOTE SET ATTRIBUTES OUT DATE          235   0 = OFF, 1 = ON
  1146. ;X  REMOTE SET ATTRIBUTES OUT CREATOR       236   0 = OFF, 1 = ON
  1147. ;X  REMOTE SET ATTRIBUTES OUT ACCOUNT       237   0 = OFF, 1 = ON
  1148. ;X  REMOTE SET ATTRIBUTES OUT AREA          238   0 = OFF, 1 = ON
  1149. ;X  REMOTE SET ATTRIBUTES OUT BLOCK-SIZE    239   0 = OFF, 1 = ON
  1150. ;X  REMOTE SET ATTRIBUTES OUT ACCESS        240   0 = OFF, 1 = ON
  1151. ;X  REMOTE SET ATTRIBUTES OUT ENCODING      241   0 = OFF, 1 = ON
  1152. ;X  REMOTE SET ATTRIBUTES OUT DISPOSITION   242   0 = OFF, 1 = ON
  1153. ;X  REMOTE SET ATTRIBUTES OUT PROTECTION    243   0 = OFF, 1 = ON
  1154. ;X  REMOTE SET ATTRIBUTES OUT GPROTECTION   244   0 = OFF, 1 = ON
  1155. ;X  REMOTE SET ATTRIBUTES OUT SYSTEM-ID     245   0 = OFF, 1 = ON
  1156. ;X  REMOTE SET ATTRIBUTES OUT FORMAT        246   0 = OFF, 1 = ON
  1157. ;X  REMOTE SET ATTRIBUTES OUT SYS-INFO      247   0 = OFF, 1 = ON
  1158. ;X  REMOTE SET ATTRIBUTES OUT BYTE-COUNT    248   0 = OFF, 1 = ON
  1159. ;
  1160. ;  REMOTE SET FILE TYPE                    300   0 = TEXT, 1 = BINARY
  1161. ;X  REMOTE SET FILE NAMES                   301   0 = CONVERTED, 1 = LITERAL
  1162. ;  REMOTE SET FILE COLLISION               302   0 = RENAME,  1 = REPLACE,
  1163. ;                                                X 2 = BACKUP,  X 3 = APPEND,
  1164. ;                                                4 = DISCARD, X  5 = ASK
  1165. ;X  REMOTE SET FILE REPLACE                 303   0 = PRESERVE, 1 = DEFAULT
  1166. ;  REMOTE SET INCOMPLETE                   310   0 = DISCARD, 1 = KEEP
  1167. ;
  1168. ;  REMOTE SET BLOCK-CHECK                  400   number (1, 2, or 3)
  1169. ;  REMOTE SET RECEIVE PACKET-LENGTH        401   number (10-9024)
  1170. ;  REMOTE SET RECEIVE TIMEOUT              402   number (any, 0 = no timeout)
  1171. ;  REMOTE SET RETRY                        403   number (any, 0 = no limit)
  1172. ;  REMOTE SET SERVER TIMEOUT               404   number (any, 0 = no timeout)
  1173. ;  REMOTE SET TRANSFER CHARACTER-SET       405   Character Set Designator
  1174. ;  REMOTE SET WINDOW-SLOTS                 406   number (1-31)
  1175. ;
  1176. ; Items marked with "X" are ignored by this server
  1177.  
  1178. ; srvset - manage incoming REMOTE SET commands
  1179. ; decode buffer looks like S<len1><value1><len2><value2>
  1180. srvset    proc    near
  1181.     mov    bufptr,offset decbuf+1    ; received command data, asciiz
  1182.     call    srvswk            ; worker to convert first value to ax
  1183.     jc    srvset3            ; c = failure
  1184.     mov    temp,ax            ; save first value here
  1185.     cmp    ax,132            ; before known set?
  1186.     jb    srvset3            ; b = yes, bad
  1187.     mov    di,offset sattr        ; assume SET ATTRIBUTES
  1188.     cmp    ax,148            ; still in range?
  1189.     jbe    srvset2            ; be = yes
  1190.     cmp    ax,232            ; before next range?
  1191.     jb    srvset1            ; b = yes
  1192.     cmp    ax,248            ; still in range?
  1193.     jbe    srvset2            ; be = yes, get final value
  1194. srvset1:push    es            ; do table lookup on other values
  1195.     push    ds
  1196.     pop    es
  1197.     mov    di,offset setval    ; look up other codes in table
  1198.     mov    cx,setvlen
  1199.     cld
  1200.     repne    scasw
  1201.     pop    es
  1202.     mov    bx,offset remms1    ; "Unknown server command", if needed
  1203.     jne    srvset3            ; ne = no match, unknown command
  1204.     sub    di,offset setval+2    ; get displacement
  1205.     mov    di,setvec[di]
  1206. srvset2:call    di            ; call the action routine
  1207.     mov    bx,offset remms6    ; "Command failed", if needed
  1208.     jc    srvset3            ; c = failure
  1209.     mov    si,offset remms8    ; "Command succeeded"
  1210.     mov    di,offset encbuf    ; destination for message
  1211.     call    strcpy            ; move the message
  1212.     mov    dx,di
  1213.     call    strlen            ; length to cx
  1214.     mov    si,offset rpacket    ; use this packet for reply
  1215.     call    doenc            ; encode
  1216.     mov    trans.chklen,1        ; reply with 1 char checksum
  1217.     call    ackpak            ; send ACK with message
  1218.     clc
  1219.     ret
  1220. srvset3:mov    trans.chklen,1        ; reply with 1 char checksum
  1221.     call    errpack            ; send error message in ptr bx
  1222.     clc
  1223.     ret
  1224. srvset    endp
  1225.  
  1226. sattr    proc    near            ; SET ATTRIBUTES IN/OUT ITEM ON/OFF
  1227.     mov    ax,temp            ; get kind of attribute
  1228.     cmp    ax,200            ; the OUT kind?
  1229.     jb    sattr1            ; b = no, IN kind
  1230.     sub    ax,100            ; merge to same thing
  1231. sattr1:    cmp    ax,132            ; ALL?
  1232.     jne    sattr2            ; be = ok
  1233.     mov    bl,0ffh            ; all bits
  1234.     jmp    short sattr6
  1235. sattr2:    cmp    al,133            ; Length?
  1236.     jne    sattr3            ; ne = no
  1237.     mov    bl,attlen
  1238.     jmp    short sattr6
  1239. sattr3:    cmp    al,134            ; Type
  1240.     jne    sattr4            ; ne = no
  1241.     mov    bl,atttype
  1242.     jmp    short sattr6
  1243. sattr4:    cmp    bl,135            ; Date?
  1244.     jne    sattr5            ; ne = no, fail
  1245.     mov    bl,attdate
  1246.     jmp    short sattr6
  1247. sattr5:    stc                ; fail
  1248.     ret
  1249. sattr6:    call    srvswk            ; get second value to ax, 1 = on
  1250.     jc    sattr5            ; c = failure
  1251.     or    ax,ax            ; off?
  1252.     jnz    sattr7            ; nz = no, on
  1253.     mov    al,flags.attflg        ; current flags
  1254.     not    bl            ; invert selected items
  1255.     and    al,bl            ; turn off selected items
  1256.     mov    flags.attflg,al        ; store the flags
  1257.     clc
  1258.     ret
  1259. sattr7:    cmp    ax,1            ; on?
  1260.     jne    sattr5            ; ne = no, fail
  1261.     or    flags.attflg,bl        ; insert ON selected bits
  1262.     clc    
  1263.     ret
  1264. sattr    endp
  1265.  
  1266. sftype    proc    near            ; SET FILE TYPE
  1267.     call    srvswk            ; get second value to ax
  1268.     jc    sftypb            ; c = failure
  1269.     cmp    al,1
  1270.     ja    sftypb            ; a = bad
  1271.     mov    trans.xtype,al        ; store transfer type
  1272.     mov    dtrans.xtype,al        ; store transfer type
  1273.     clc
  1274.     ret
  1275. sftypb:    stc                ; bad command
  1276.     ret
  1277. sftype    endp
  1278.  
  1279. sfcoll    proc    near            ; SET FILE COLLISION
  1280.     call    srvswk            ; get second value to ax
  1281.     jc    sfcollb            ; c = failure
  1282.     cmp    ax,4
  1283.     ja    sfcollb            ; a = bad
  1284.     cmp    ax,2            ; backup?
  1285.     je    sfcollb            ; e = yes, bad command
  1286.     cmp    ax,3            ; append?
  1287.     je    sfcollb            ; e = yes, bad command
  1288.     mov    flags.flwflg,al        ; set file collison state
  1289.     clc
  1290.     ret
  1291. sfcollb:stc                ; bad command
  1292.     ret
  1293. sfcoll    endp
  1294.  
  1295. sfinc    proc    near             ; SET INCOMPLETE, SET FILE INCOMPLETE
  1296.     call    srvswk            ; get second value to ax
  1297.     jc    sfincb            ; c = failure
  1298.     cmp    ax,1
  1299.     ja    sfincb            ; a = bad
  1300.     mov    flags.abfflg,al        ; discard incomplete files if al = 1
  1301.     clc
  1302.     ret
  1303. sfincb:    stc                ; bad command
  1304.     ret
  1305. sfinc    endp
  1306.  
  1307. srtmo    proc    near            ; SET RECEIVE TIMEOUT
  1308.     call    srvswk            ; get second value to ax
  1309.     jnc    srtmo1            ; nc = success
  1310.     ret
  1311. srtmo1:    cmp    ax,94            ; above limit?
  1312.     jbe    srtmo2            ; be = no
  1313.     mov    al,94
  1314. srtmo2:    mov    trans.rtime,al
  1315.     clc
  1316.     ret
  1317. srtmo    endp
  1318.  
  1319. sblkck    proc    near            ; SET BLOCK-CHECK
  1320.     call    srvswk            ; get second value to ax
  1321.     jnc    sblkck1            ; nc = success
  1322.     ret                ; fail
  1323. sblkck1:cmp    ax,3            ; our limit
  1324.     jbe    sblkck2            ; be = safe
  1325.     mov    ax,3            ; set to max
  1326. sblkck2:or    ax,ax            ; too small?
  1327.     jnz    sblkck3            ; z = no
  1328.     inc    ax
  1329. sblkck3:mov    dtrans.chklen,al    ; use this char as initial checksum
  1330.     clc
  1331.     ret
  1332. sblkck    endp
  1333.  
  1334. srpkt    proc    near             ; SET RECEIVE PACKET-LENGTH
  1335.     call    srvswk            ; get second value to ax
  1336.     jnc    srpkt1            ; nc = success
  1337.     ret
  1338. srpkt1:    cmp    ax,maxpack        ; above limit?
  1339.     jbe    srpkt2            ; be = no
  1340.     mov    ax,maxpack
  1341. srpkt2:    cmp    ax,20            ; too small?
  1342.     jae    srpkt3            ; ae = no
  1343.     mov    ax,20            ; set minimum
  1344. srpkt3:    mov    dtrans.rlong,ax        ; set long packet size
  1345.     mov    bl,dtrans.rpsiz        ; regular packet size
  1346.     xor    bh,bh
  1347.     cmp    ax,bx            ; is long packet shorter
  1348.     jae    srpkt4            ; ae = no
  1349.     mov    dtrans.rpsiz,al        ; set regular pkt length too
  1350. srpkt4:    clc
  1351.     ret
  1352. srpkt    endp
  1353.  
  1354. sretry    proc    near            ; REMOTE SET RETRY
  1355.     call    srvswk            ; get second value to ax
  1356.     jnc    sretry1            ; nc = success
  1357.     ret                ; fail
  1358. sretry1:cmp    ax,63            ; our limit
  1359.     jbe    sretry2            ; be = safe
  1360.     mov    ax,63            ; set to max
  1361. sretry2:mov    maxtry,al        ; set packet retry limit
  1362.     clc
  1363.     ret
  1364. sretry    endp
  1365.  
  1366. sstmo    proc    near            ; SET SERVER TIMEOUT
  1367.     call    srvswk            ; get second value to ax
  1368.     jnc    sstmo1            ; nc = success
  1369.     ret
  1370. sstmo1:    cmp    ax,255
  1371.     jbe    sstmo2            ; be = in range
  1372.     mov    al,255            ; limit to max
  1373. sstmo2:    mov    srvtmo,al        ; store timeout value
  1374.     clc
  1375.     ret
  1376. sstmo    endp
  1377.  
  1378. sxfrch    proc    near            ; SET TRANSFER CHARACTER-SET string
  1379.     mov    bx,bufptr
  1380.     xor    ch,ch
  1381.     mov    cl,[bx]            ; byte count of next field, if any
  1382.     sub    cl,' '            ; remove ascii bias
  1383.     jnc    sxfrch1            ; nc = is ok
  1384.     ret
  1385. sxfrch1:inc    bx            ; look at character string
  1386.     cmp    byte ptr[bx],'A'    ; A for Transparent?
  1387.     jne    sxfrch2
  1388.     cmp    cx,1            ; just that char?
  1389.     jne    sxfrchb            ; ne = no, fail
  1390.     mov    trans.xchset,0        ; set transfer char set to Transparent
  1391.     clc
  1392.     ret
  1393. sxfrch2:cmp    cx,6            ; "I2/100"?
  1394.     jne    sxfrchb            ; ne = no, fail
  1395.     cmp    word ptr [bx],'2I'    ; length is ok, check spelling
  1396.     jne    sxfrchb            ; ne = failure
  1397.     cmp    word ptr [bx+2],'1/'
  1398.     jne    sxfrchb
  1399.     cmp    word ptr [bx+4],'00'
  1400.     jne    sxfrchb
  1401.     mov    trans.xchset,1        ; set transfer char set to Latin1
  1402.     clc
  1403.     ret
  1404. sxfrchb:stc                ; fail
  1405.     ret
  1406. sxfrch    endp
  1407.  
  1408. swind    proc    near            ; SET WINDOW-SLOTS
  1409.     call    srvswk            ; get second value to ax
  1410.     jnc    swind1            ; nc = success
  1411.     ret
  1412. swind1:    cmp    ax,31            ; max legal
  1413.     jbe    swind2            ; be = in range
  1414.     mov    al,31            ; limit to max
  1415. swind2:    or    ax,ax            ; no windowing?
  1416.     jnz    swind3            ; nz = no, not that way
  1417.     mov    ax,1            ; local min size for no windowing
  1418. swind3:    mov    dtrans.windo,al        ; store default window size
  1419.     clc
  1420.     ret
  1421. swind    endp
  1422.  
  1423. ; Worker for srvset. Reads buffer pointed at by bufptr looking for 
  1424. ; construction <length><numbers>. Returns carry clear and binary number
  1425. ; in AX, else carry set and AX = -1. Bufptr is always updated.
  1426. srvswk    proc    near
  1427.     push    bx
  1428.     push    cx
  1429.     push    dx
  1430.     push    si
  1431.     mov    bx,bufptr
  1432.     xor    ch,ch
  1433.     mov    cl,[bx]            ; byte count of next field, if any
  1434.     sub    cl,' '            ; remove ascii bias
  1435.     jnc    srvswk1            ; nc = is ok
  1436.     mov    ax,-1            ; else say value is -1
  1437.     jmp    short srvswkx
  1438. srvswk1:inc    bx
  1439.     xor    si,si            ; accumulated value
  1440.     mov    dl,10
  1441. srvswk2:mov    ax,si            ; accumulated value
  1442.     mul    dl            ; times 10
  1443.     mov    si,ax            ; store
  1444.     xor    ah,ah
  1445.     mov    al,[bx]            ; get a digit
  1446.     inc    bx
  1447.     sub    al,'0'            ; remove ascii bias
  1448.     jnc    srvswk3            ; nc = no
  1449.     mov    ax,-1            ; say bad value
  1450.     jmp    short srvswkx        ; and quit
  1451. srvswk3:add    si,ax            ; accumulate new digit
  1452.     loop    srvswk2            ; do all digits
  1453.     mov    ax,si            ; return results in ax
  1454.     clc
  1455. srvswkx:mov    bufptr,bx        ; remember where we read from decbuf
  1456.     pop    si
  1457.     pop    dx
  1458.     pop    cx
  1459.     pop    bx
  1460.     ret
  1461. srvswk    endp
  1462.  
  1463. ; srvini - init parms based on 'I' init packet
  1464. srvini    proc    near
  1465.     call    spar            ; parse info
  1466.     call    packlen
  1467.     call    makebuf            ; remake buffers for new windowing
  1468.     push    si
  1469.     mov    si,offset rpacket
  1470.     call    rpar            ; setup info about our reception
  1471.     pop    si
  1472.     mov    al,trans.chklen        ; checksum length negotiated
  1473.     push    ax            ; save around reply
  1474.     mov    trans.chklen,1        ; reply with 1 char checksum
  1475.     call    ackpak
  1476.     pop    ax            ; restore checksum length
  1477.     mov    dtrans.chklen,al    ;  to negotiation value
  1478.     clc                ; success
  1479.     ret
  1480. srvini    endp
  1481.  
  1482.  
  1483. ; BYE command - tell remote KERSRV to logout & exit to DOS  
  1484.  
  1485. BYE    PROC    NEAR
  1486.     mov    ah,cmeol        ; get a confirm
  1487.     call    comnd
  1488.     jnc    bye1            ; nc = success
  1489.     ret                ; failure
  1490. bye1:    mov    remcmd,'L'        ; Logout command letter
  1491.     call    logo            ; tell the host Kermit to logout
  1492.      jc    bye2            ; c = failed, do not exit
  1493.     mov    flags.extflg,1        ; set this Kermit's exit flag
  1494.     call    serhng            ; hangup the phone
  1495. bye2:    clc
  1496.     ret
  1497. BYE    ENDP
  1498.  
  1499. ; FINISH - tell    remote KERSRV to exit
  1500.  
  1501. FINISH    PROC    NEAR
  1502.     mov    ah,cmeol        ; get a confirm
  1503.     call    comnd
  1504.     jnc    finish1            ; nc = success
  1505.     ret                ; failure
  1506. finish1:mov    remcmd,'F'        ; Finish command letter
  1507.     call    logo
  1508.     clc
  1509.     ret
  1510. FINISH    ENDP
  1511.  
  1512. ; LOGOUT - tell remote KERSRV to logout
  1513.  
  1514. LOGOUT    PROC    NEAR
  1515.     mov    ah,cmeol
  1516.     call    comnd            ; get a confirm
  1517.     jnc    logout1            ; nc = success
  1518.     ret                ; failure
  1519. logout1:mov    remcmd,'L'        ; Logout command letter
  1520.     call    logo
  1521.     clc
  1522.     ret
  1523. LOGOUT    ENDP
  1524.  
  1525. ; Common routine for FINISH, LOGOUT, BYE
  1526. ; Return carry clear for success, else carry set
  1527. LOGO    PROC    NEAR
  1528.     call    serini            ; Initialize port
  1529.     jnc    logo1            ; nc = success
  1530.     ret                ; c = failure
  1531. logo1:    call    clrbuf            ; clear serial port buffer
  1532.     call    ihostr            ; initialize the host
  1533.     call    makebuf            ; set up packet buffers
  1534.     xor    ax,ax
  1535.     mov    diskio.string,al    ; clear local filename for stats
  1536.     mov    pktnum,al        ; packet number to be used
  1537.     mov    windlow,al        ; reset windowing
  1538.     call    packlen            ; get max packet length
  1539.     call    getbuf            ; get buffer for sending
  1540.     mov    trans.chklen,1        ; use one char for server functions
  1541.     mov    ah,remcmd        ; get command letter ('L' or 'F')
  1542.     mov    encbuf,ah        ; encode the command
  1543.     mov    cx,1            ; one piece of data
  1544.     call    doenc            ; do encoding
  1545.     mov    [si].pktype,'G'        ; Generic command packet type
  1546.     mov    flags.xflg,1        ; say receiving to screen
  1547.     call    sndpak            ;  to suppress # pkts msg
  1548.     jc    logo3            ; c = failure
  1549.     mov    al,[si].seqnum        ; get response for this sequence num
  1550.     mov    ah,maxtry        ; retry threshold
  1551.     call    response        ; get response
  1552.     pushf
  1553.     mov    si,offset rpacket    ; packet to look at
  1554.     cmp    [si].pktype,'E'        ; Error packet?
  1555.     je    logo2            ; e = yes, contents displayed already
  1556.     call    msgmsg            ; show any message
  1557. logo2:    popf
  1558. logo3:    mov    flags.cxzflg,0        ; clear these flags
  1559.     mov    flags.xflg,0
  1560.     ret                ; exit with carry flag from response
  1561. LOGO    ENDP
  1562.  
  1563. ; GET command. Ask remote server to send the specified file(s)
  1564. ; Queries for remote filename and optional local override path/filename
  1565. GET    PROC    NEAR
  1566.     mov    auxfile,0        ; clear, for safety
  1567.     mov    encbuf,0        ; ditto
  1568.     mov    flags.cxzflg,0        ; no Control-C typed yet
  1569.     mov    bx,offset encbuf    ; where to put text
  1570.     mov    dx,offset filmsg    ; help
  1571.     mov    ah,cmline        ; filenames with embedded whitespace
  1572.     call    comnd            ; get text or confirm
  1573.     jnc    get1            ; nc = success
  1574.     ret                ; failure 
  1575. get1:    mov    cnt,ax            ; remember number of chars we read
  1576.     or    ax,ax            ; read in any chars?
  1577.     jnz    get7            ; nz = yes, analyze
  1578.                     ; if empty line, ask for file names
  1579. get2:    mov    dx,offset remfnm    ; ask for remote name first
  1580.     call    prompt
  1581.     mov    bx,offset encbuf    ; place for remote filename
  1582.         mov    dx,offset frem        ; help message
  1583.     mov    ah,cmline        ; use this for embedded spaces
  1584.     call    comnd            ; get a filename
  1585.     jnc    get3            ; nc = success
  1586.     ret                ; failure
  1587. get3:    mov    cnt,ax            ; remember number of chars read
  1588.     or    ax,ax            ; count of entered chars
  1589.     jz    get2            ; z = none, try again
  1590.     mov    dx,offset lclfnm    ; prompt for local filename
  1591.     call    prompt
  1592.     mov    bx,offset filhlp
  1593.     mov    dx,offset auxfile    ; complete local filename
  1594.     mov    auxfile,0        ; clear, for safety
  1595.     mov    ah,cmword        ; get a word
  1596.     call    comnd
  1597.     jnc    get5            ; nc = success
  1598.     ret                ; failure
  1599. get5:    mov    ah,cmeol        ; get confirmation
  1600.     call    comnd
  1601.     jnc    get6            ; nc = success
  1602.     ret                ; failure
  1603. get6:    cmp    auxfile,'#'        ; is first char a replacement for '?'
  1604.     jne    get7            ; ne = no
  1605.     mov    auxfile,'?'        ; replace '#' by '?'
  1606. get7:    cmp    encbuf,'#'        ; is first char a replacement for '?' ?
  1607.     jne    get8            ; ne = no
  1608.     mov    encbuf,'?'        ; replace '#' by '?'
  1609.  
  1610. get8:    call    rrinit            ; clear buffers and counters
  1611.     mov    flags.xflg,1        ; assume writing to screen
  1612.     cmp    flags.destflg,2        ; receiving to screen?
  1613.     je    get8a            ; e = yes, skip screen stuff
  1614.     mov    flags.xflg,0        ; not writing to screen, yet
  1615.     call    init            ; init (formatted) screen
  1616. get8a:    call    begtim            ; start statistics
  1617.     mov    kstatus,kssuc        ; global status, success
  1618.     call    makebuf            ; setup packet buffers
  1619.     call    ipack            ; Send Initialize, 'I', packet
  1620.     jnc    get8b            ; nc = success, ok to fail 'I' pkt
  1621.     jmp    short get10        ; failure
  1622.  
  1623. get8b:    mov    si,offset encbuf    ; copy from here
  1624.     mov    di,offset fsta.xname    ; to statistics remote name field
  1625.     call    strcpy
  1626.     mov    si,offset rpacket    ; packet for response
  1627.     mov    cx,cnt            ; get back remote filename size
  1628.     call    doenc            ; encode data already in encbuf
  1629.     jnc    get9            ; nc = success
  1630.     mov    dx,offset ermes6        ; filename is too long for pkt
  1631.     call    ermsg
  1632.     mov    bx,dx            ; point to message, for errpack
  1633.     call    errpack            ; tell the host we are quiting
  1634.     jmp    short get10        ; data could not all fit into packet
  1635.  
  1636. get9:    mov    trans.chklen,1        ; use one char for server functions
  1637.     mov    rpacket.pktype,'R'    ; Receive init packet
  1638.     mov    si,offset rpacket
  1639.     call    sndpak            ; send the packet, no ACK expected
  1640.     jc    get10            ; c = failure to send packet
  1641.     mov    rstate,'R'        ; Set the state to receive initiate
  1642.     jmp    READ2            ; go join read code
  1643.  
  1644. get10:    call    bufclr            ; total failures come here
  1645.     call    rprpos            ; reset cursor for prompt
  1646.     or    errlev,ksrecv        ; set DOS error level to cannot rcv
  1647.     or    fsta.xstatus,ksrecv    ; set status
  1648.     mov    kstatus,ksrecv        ; global status
  1649.     mov    flags.cxzflg,0        ; clear flag for next command
  1650.     mov    auxfile,0        ; clear send-as filename buffer
  1651.     mov    flags.xflg,0        ; clear to-screen flag
  1652.     clc
  1653.     ret
  1654. GET    ENDP
  1655.  
  1656. ;    This is the REMOTE command
  1657.  
  1658. REMOTE    PROC    NEAR
  1659.     mov    dx,offset remtab    ; Parse keyword from the REMOTE table
  1660.     mov    bx,offset remhlp
  1661.     mov    ah,cmkey
  1662.     call    comnd
  1663.     jnc    remote1            ; nc = success
  1664.     ret                ; failure
  1665. remote1:jmp    bx            ; do the appropriate routine
  1666. REMOTE    ENDP
  1667.  
  1668. ; REMSET - Execute a REMOTE SET command
  1669.  
  1670. REMSET    PROC    NEAR
  1671.     mov    rempac,'G'        ; Packet type = generic
  1672.     mov    encbuf,'S'        ; command type = Set
  1673.     mov    bufptr,offset encbuf+1    ; place more pkt material here
  1674.     mov    ah,cmkey        ; get keyword
  1675.     mov    dx,offset remstt1    ; table of keywords
  1676.     xor    bx,bx            ; help
  1677.     call    comnd
  1678.     jnc    remset1            ; nc = success
  1679.     ret
  1680. remset1:cmp    bx,1            ; Attributes?
  1681.     jne    remset5            ; ne = no
  1682.     mov    dx,offset remsat1    ; Attributes IN, OUT table
  1683.     xor    bx,bx            ; help
  1684.     mov    ah,cmkey
  1685.     call    comnd
  1686.     jnc    remset2
  1687.     ret
  1688. remset2:mov    temp,bx            ; save in out
  1689.     mov    dx,offset remsat2    ; next attributes keyword table
  1690.     xor    bx,bx            ; help
  1691.     mov    ah,cmkey
  1692.     call    comnd
  1693.     jnc    remset3
  1694.     ret
  1695. remset3:add    bx,temp            ; save final value
  1696.     call    remwork
  1697.     mov    dx,offset onoff        ; ON, OFF table
  1698.     xor    bx,bx            ; help
  1699.     mov    ah,cmkey        ; get on,off
  1700.     call    comnd
  1701.     jnc    remset4
  1702.     ret
  1703. remset4:jmp    remset17
  1704.  
  1705. remset5:cmp    bx,2            ; REMOTE SET FILE?
  1706.     jne    remset14        ; ne = no
  1707.     mov    dx,offset remsfit    ; REM SET FILE table
  1708.     xor    bx,bx            ; help
  1709.     mov    ah,cmkey
  1710.     call    comnd
  1711.     jnc    remset6
  1712.     ret
  1713. remset6:push    bx
  1714.     call    remwork            ; write kind to buffer
  1715.     pop    bx
  1716.     cmp    bx,300            ; TYPE?
  1717.     jne    remset8
  1718.     mov    dx,offset remsfty    ; TYPE table
  1719.     xor    bx,bx
  1720.     mov    ah,cmkey
  1721.     call    comnd
  1722.     jnc    remset17
  1723.     ret
  1724.  
  1725. remset8:cmp    bx,301            ; NAME?
  1726.     jne    remset10        ; ne = no
  1727.     mov    dx,offset remsfna    ; NAME table
  1728.     xor    bx,bx
  1729.     mov    ah,cmkey
  1730.     call    comnd
  1731.     jnc    remset17
  1732.     ret
  1733.  
  1734. remset10:cmp    bx,302            ; COLLISION?
  1735.     jne    remset12        ; ne = no
  1736.     mov    dx,offset remsfco    ; COLLISION table
  1737.     xor    bx,bx
  1738.     mov    ah,cmkey
  1739.     call    comnd
  1740.     jnc    remset17
  1741.     ret
  1742.  
  1743. remset12:cmp    bx,303            ; REPLACE?
  1744.     jne    remset13        ; ne = no
  1745.     mov    dx,offset remsfre    ; REPLACE table
  1746.     xor    bx,bx
  1747.     mov    ah,cmkey
  1748.     call    comnd
  1749.     jnc    remset17
  1750.     ret
  1751.  
  1752. remset13:cmp    bx,310            ; INCOMPLETE?
  1753.     jne    remset13a        ; ne = no
  1754.     mov    dx,offset remsfin    ; INCOMPLETE table
  1755.     xor    bx,bx
  1756.     mov    ah,cmkey
  1757.     call    comnd
  1758.     jnc    remset17
  1759. remset13a:stc
  1760.     ret
  1761.  
  1762. remset14:cmp    bx,310            ; REMOTE SET INCOMPLETE?
  1763.     jne    remset15        ; ne = no
  1764.     push    bx
  1765.     call    remwork            ; write main command
  1766.     pop    bx
  1767.     jmp    short remset13        ; use above to complete the command
  1768.  
  1769. remset15:cmp    bx,3            ; REMOTE SET RECEIVE?
  1770.     jne    remset18        ; ne = no
  1771.     mov    dx,offset remsrcv    ; RECEIVE table
  1772.     xor    bx,bx
  1773.     mov    ah,cmkey
  1774.     call    comnd
  1775.     jnc    remset19        ; get value as text
  1776. remset16:stc
  1777.     ret
  1778.  
  1779. remset17:call    remwork            ; write to buffer
  1780.     jmp    short remset22
  1781.                     ; text as last item commands
  1782. remset18:mov    temp,bx
  1783.     cmp    bx,405            ; Transfer?
  1784.     jne    remset19        ; ne = no
  1785.     mov    dx,offset remsxfr    ; TRANSFER table
  1786.     xor    bx,bx
  1787.     mov    ah,cmkey
  1788.     call    comnd
  1789.     jnc    remset19
  1790.     ret
  1791. remset19:call    remwork            ; store command type
  1792.     mov    dx,bufptr        ; store response as text
  1793.     inc    dx            ; skip count byte
  1794.     mov    bx,offset numhlp
  1795.     cmp    temp,405        ; Transfer character set needs string
  1796.     jne    remset20        ; ne = not string
  1797.     mov    bx,offset xfrhlp    ; use this help
  1798. remset20:mov    ah,cmword
  1799.     call    comnd
  1800.     jnc    remset21
  1801.     ret
  1802. remset21:mov    dx,bufptr        ; field pointer
  1803.     inc    dx            ; look at text
  1804.     call    strlen            ; length to cx
  1805.     add    cx,' '            ; compute byte count field
  1806.     mov    bx,bufptr
  1807.     mov    [bx],cl            ; store byte count
  1808.  
  1809. remset22:mov    ah,cmeol        ; get a confirmation
  1810.     call    comnd
  1811.     jnc    remset23
  1812.     ret
  1813. remset23:mov    dx,offset encbuf
  1814.     call    strlen            ; get length
  1815.     mov    cnt,cx            ; length for generic
  1816.     mov    flags.xflg,1        ; response coming to screen
  1817.     jmp    genr9            ; do the operation
  1818. REMSET    ENDP
  1819.  
  1820. ; Remote Set worker. Enter with new numerical value in BX. Writes length
  1821. ; and asciiz value to encbuf and increments buffer pointer bufptr.
  1822. remwork    proc    near
  1823.     mov    di,offset tmpbuf    ; temp buffer
  1824.     mov    byte ptr [di],0        ; clear it
  1825.     mov    ax,bx
  1826.     call    dec2di            ; convert value to asciiz
  1827.     mov    dx,offset tmpbuf    ; get length to cx
  1828.     mov    si,dx            ; asciiz data source
  1829.     call    strlen
  1830.     push    cx            ; save length
  1831.     mov    di,bufptr        ; byte count field
  1832.     add    cl,' '            ; to ascii
  1833.     mov    [di],cl            ; store count byte
  1834.     inc    di
  1835.     pop    cx
  1836.     push    es
  1837.     push    ds
  1838.     pop    es
  1839.     cld
  1840.     rep    movsb            ; copy asciiz data value
  1841.     pop    es
  1842.     mov    byte ptr [di],0        ; insert null terminator
  1843.     mov    bufptr,di
  1844.     ret
  1845. remwork    endp
  1846.  
  1847. ; In REM commands below, al = remcmd, ah = rempac, cl = remlen
  1848. ; REMCWD - Change remote working directory
  1849.  
  1850. REMCWD    PROC    NEAR
  1851.     mov    ax,'GC'            ; Packet type = generic
  1852.     xor    cl,cl            ; no text required
  1853.     jmp    genric
  1854. REMCWD    ENDP
  1855.  
  1856. ; REMDEL - Delete a remote file
  1857.  
  1858. REMDEL    PROC    NEAR
  1859.     mov    ax,'GE'            ; Packet type = generic
  1860.     mov    cl,1            ; text required
  1861.     jmp    genric
  1862. REMDEL    ENDP
  1863.  
  1864. ; REMDIR - Do a directory
  1865.  
  1866. REMDIR    PROC    NEAR
  1867.     mov    ax,'GD'            ; Packet type = generic
  1868.     xor    cl,cl            ; no text required
  1869.     jmp    genric
  1870. REMDIR    ENDP
  1871.  
  1872. ; REMDIS - Get disk usage on remote system
  1873.  
  1874. REMDIS    PROC    NEAR
  1875.     mov    ax,'GU'            ; Packet type = generic, disk usage
  1876.     xor    cl,cl            ; optional text permitted
  1877.     jmp    genric            ; Execute generic Kermit command
  1878. REMDIS    ENDP
  1879.  
  1880.  
  1881. ; REMHEL - Get help about remote commands
  1882.  
  1883. REMHEL    PROC    NEAR
  1884.     mov    ax,'GH'            ; Packet type = generic, Help
  1885.     xor    cl,cl            ; no text required
  1886.     jmp    genric            ; Execute generic Kermit command
  1887. REMHEL    ENDP
  1888.  
  1889. ; REMHOS - Execute a remote host command
  1890.  
  1891. REMHOS    PROC    NEAR
  1892.     mov    ax,'C '            ; Packet type = remote command
  1893.     mov    cl,1            ; text required
  1894.     jmp    genric
  1895. REMHOS    ENDP
  1896.  
  1897. ; REMKER - Execute a remote Kermit command
  1898.  
  1899. REMKER    PROC    NEAR
  1900.     mov    ax,'K '            ; Packet type = remote Kermit command
  1901.     mov    cl,1            ; text required
  1902.     jmp    short genric
  1903. REMKER    ENDP
  1904.  
  1905. ; REMLOGIN - LOGIN [username [password [account]]]
  1906.  
  1907. REMLOGIN PROC    NEAR
  1908.     mov    ax,'GI'            ; Packet type = generic
  1909.     xor    cl,cl            ; no text required
  1910.     jmp    short genric
  1911. REMLOGIN ENDP
  1912.  
  1913. ; REMMSG - Send one line short message to remote screen.
  1914.  
  1915. REMMSG    proc    near
  1916.     mov    ax,'GM'
  1917.     mov    cl,1            ; text required
  1918.     jmp    short genric
  1919. REMMSG    endp
  1920.  
  1921. ; REMTYP - Type a remote file
  1922.  
  1923. REMTYP    PROC    NEAR
  1924.     mov    ax,'GT'            ; Packet type = generic, Type file
  1925.     mov    cl,1            ; text required
  1926.     jmp    short genric
  1927. REMTYP    ENDP
  1928.  
  1929. ; REMWHO - ask for list of remote logged on users
  1930.  
  1931. REMWHO    proc    near
  1932.     mov    ax,'GW'
  1933.     xor    cl,cl            ; optional text permitted
  1934.     jmp    short genric
  1935. REMWHO    endp
  1936.  
  1937. ; GENRIC - Send a generic command to a remote Kermit server
  1938. ; remlen = 0: no additional text, or additional text is optional
  1939. ; remlen = 1: additional text is required
  1940. GENRIC    PROC    NEAR
  1941.     mov    remcmd,al        ; stash cmd info in real memory
  1942.     mov    rempac,ah        ; packet type
  1943.     mov    remlen,cl        ; text required flag
  1944.     mov    si,offset infms3    ; dummy filename for transaction log
  1945.     mov    di,offset diskio.string    ; where such names go
  1946.     call    strcpy            ; move the name
  1947.     mov    bx,offset encbuf    ; where to put text
  1948.     mov    temp,bx            ; where field starts
  1949.     cmp    rempac,'C'        ; Remote Host command? 
  1950.     je    genr2            ; e = yes, no counted string(s)
  1951.     cmp    rempac,'K'        ; Remote Kermit command?
  1952.     je    genr2            ; e = yes, no counted string(s)
  1953. genr1:    mov    ah,remcmd        ; get command letter
  1954.     mov    [bx],ah            ; store in buffer
  1955.     add    bx,2            ; leave room for count byte
  1956.     mov    temp,bx            ; point at data field
  1957. genr2:    mov    ah,cmline        ; get a line text
  1958.     mov    dx,offset genmsg    ; help message
  1959.     call    comnd
  1960.     jnc    genr3            ; nc = success
  1961.     ret                ; failure
  1962. genr3:    mov    cnt,ax            ; size
  1963.     call    genredir        ; act on any ">filespec" redirection
  1964.     add    temp,ax            ; point to next field
  1965.     cmp    rempac,'C'        ; Remote Host command?
  1966.     je    genr4            ; e = yes, no counted string(s)
  1967.     cmp    rempac,'K'        ; Remote Kermit command?
  1968.     je    genr4            ; e = yes, no counted string(s)
  1969.     mov    encbuf+1,al        ; size of first field
  1970.     add    encbuf+1,32        ; do tochar function
  1971.     inc    temp            ; include count byte
  1972. genr4:    cmp    al,remlen        ; got necessary command text?
  1973.     jae    genr5            ; ae = yes
  1974.     cmp    remlen,0        ; is text optional?
  1975.     je    genr5            ; e = yes, continue without it
  1976. genr4a:    mov    dx,offset infms2    ; say need more info
  1977.     mov    ah,prstr
  1978.     int    dos
  1979.     or    errlev,ksgen        ; say cannot receive
  1980.     or    fsta.xstatus,ksgen    ; set status failed
  1981.     mov    kstatus,ksgen        ; global status
  1982.     clc
  1983.     ret
  1984.  
  1985. genr5:    mov    flags.xflg,1        ; output coming to screen
  1986.     cmp    remcmd,'I'        ; Remote Login command?
  1987.     je    genr6            ; e = yes
  1988.     cmp    remcmd,'C'        ; Remote Change Working Directory?
  1989.     je    genr7a            ; e = yes, get optional password
  1990.     jmp    short genr8        ; neither so no extra prompts here
  1991.  
  1992. genr6:    cmp    cnt,0            ; have username etc already?
  1993.     je    genr6a            ; e = no
  1994.     call    genupwd            ; parse username etc
  1995.     jmp    short genr8        ; send formatted contents
  1996. genr6a:    mov    dx,offset user        ; prompt for username
  1997.      call    prompt
  1998.     mov    bx,offset encbuf+1    ; skip command letter
  1999.     mov    temp,bx            ; start of field
  2000.     call    input            ; read text
  2001.     jc    genr8            ; c = none
  2002.     mov    temp,bx            ; point to next data field
  2003.  
  2004. genr7:    mov    dx,offset password    ; get optional password
  2005.     call    prompt
  2006. genr7a:    mov    bx,temp            ; where to put the password
  2007.     cmp    byte ptr [bx-1],0    ; extra null?
  2008.     jne    genr7b            ; ne = no
  2009.     dec    bx            ; backup to overwrite it
  2010.     dec    temp
  2011. genr7b:    mov    comand.cmquiet,1    ; turn on quiet mode
  2012.     call    input            ; read in the password
  2013.     mov    comand.cmquiet,0    ; turn off quiet mode
  2014.     jc    genr8            ; c = no text, do not add field
  2015.     mov    temp,bx            ; point to next data field
  2016.                     ;
  2017.     cmp    remcmd,'I'        ; Remote Login command?
  2018.     jne    genr8            ; ne = no
  2019.     mov    dx,offset account    ; get optional account ident
  2020.     call    prompt
  2021.     mov    bx,temp            ; where this field starts
  2022.     call    input            ; read text
  2023. genr8:    cmp    flags.cxzflg,'C'    ; Control-C entered?
  2024.     jne    genr9            ; ne = no
  2025.     stc
  2026.     ret                ; return failure
  2027.  
  2028. GENR9:    mov    kstatus,kssuc        ; global status
  2029.     call    ipack            ; Send Init parameters
  2030.     jc    genr11            ; c = failure
  2031.     mov    trans.chklen,1        ; use 1 char for server functions
  2032.     mov    fsta.pretry,0        ; no retries yet
  2033.     mov    pktnum,0
  2034.     cmp    flags.cxzflg,'C'    ; did the user type a ^C?
  2035.     jne    genr10            ; ne = no
  2036.     stc
  2037.     ret                ; return in error state
  2038.  
  2039. genr10:    push    si
  2040.     mov    si,offset rpacket    ; use this packet for reply
  2041.     mov    dx,offset encbuf
  2042.     call    strlen            ; length of data
  2043.     call    doenc            ; encode data
  2044.     mov    trans.chklen,1        ; use block check 1 to server
  2045.     mov    ah,rempac        ; packet type
  2046.     mov    rpacket.pktype,ah
  2047.     call    sndpak            ; send the Generic command packet
  2048.     pop    si
  2049.     jc    genr11            ; c = failure
  2050.     mov    rstate,'R'        ; next state is Receive Initiate
  2051.     jmp    READ2            ; file receiver does the rest
  2052.  
  2053. genr11:    mov    flags.xflg,0        ; reset screen output flag
  2054.     xor    ax,ax            ; tell statistics this was a read
  2055.     or    errlev,ksrem         ; DOS error level, failure of REMote cmd
  2056.     mov    fsta.xstatus,ksrem    ; set status
  2057.     mov    kstatus,ksrem        ; global status
  2058.     clc
  2059.     ret
  2060. GENRIC    ENDP
  2061.  
  2062. ; Extract ">filespec" redirection at end of command line. If found put
  2063. ; filespec in auxfile as new output name.
  2064. genredir proc    near
  2065.     mov    cx,cnt            ; chars on command line
  2066.     jcxz    genred3            ; z = none
  2067.     mov    di,temp            ; buffer, after prologue
  2068.     add    di,cx            ; end of buffer+1
  2069.     dec    di
  2070.     push    ax
  2071.     push    es
  2072.     mov    ax,ds
  2073.     mov    es,ax
  2074.     mov    al,'>'            ; redirection symbol
  2075.     std                ; scan backward
  2076.     repne    scasb            ; found '>'?
  2077.     cld
  2078.     pop    es
  2079.     pop    ax
  2080.     jne    genred3            ; ne = no
  2081.     inc    di            ; look at '>'
  2082.     mov    byte ptr[di],0        ; insert terminator
  2083.     mov    ax,cx            ; new count length
  2084.     mov    cnt,cx            ; remember here too
  2085. genred1:inc    di            ; look at optional filename
  2086.     or    di,di            ; terminator?
  2087.     jz    genred2            ; z = yes
  2088.     cmp    byte ptr [di],' '    ; remove lead-in puncutation
  2089.     jbe    genred1            ; be = punctuation, go until text
  2090. genred2:mov    si,di
  2091.     mov    di,offset auxfile    ; new output name goes here
  2092.     call    strcpy
  2093. genred3:ret
  2094. genredir endp
  2095.  
  2096. ; Parse a single command line into username, password, account in counted
  2097. ; string style, for REM LOGIN. Enter with BX pointing at the next new
  2098. ; byte to store a command character and CNT holding the current line length.
  2099. ; Returns a completely formatted line, asciiz. Use {..} to surround items
  2100. ; with embedded spaces.
  2101. genupwd    proc    near
  2102.     push    ax
  2103.     push    bx
  2104.     push    es
  2105.     mov    ax,ds
  2106.     mov    es,ax
  2107.     sub    bx,cnt            ; next item minus count of items
  2108.     mov    si,bx            ; where text starts
  2109.     dec    bx            ; point at count byte
  2110.     mov    cx,3            ; three fields possible
  2111. genupw1:push    cx
  2112.     mov    cx,cnt            ; number of text chars to examine
  2113.     call    genup10            ; get first field
  2114.     mov    cnt,cx            ; update remaining count
  2115.     or    cx,cx            ; get remaining count
  2116.     pop    cx            ; recover loop counter
  2117.     jz    genupw2            ; z means empty remainder
  2118.     loop    genupw1            ; try to do three fields
  2119. genupw2:pop    es
  2120.     pop    bx
  2121.     pop    ax
  2122.     ret
  2123.  
  2124. ; Worker. Enter with bx=offset of count byte, si=offset of start of text,
  2125. ;  cx=chars remaining in input string.
  2126. ; Exit with bx=offset of next count byte, si=offset of where new text is
  2127. ; to be read, cx=chars remaining in input string.
  2128. genup10:mov    byte ptr [bx],' '    ; clear count byte to zero + space
  2129.     mov    di,si            ; work on text part
  2130.     mov    al,' '            ; skip whitespace
  2131.     cld
  2132.     repe    scasb
  2133.     je    genup12            ; e = nothing present
  2134.     dec    di            ; back up to non-white char
  2135.     inc    cx            ; correct count
  2136.     mov    si,di            ; si = where non-white text starts
  2137.     mov    di,bx            ; count byte
  2138.     inc    di            ; where text goes
  2139.     mov    ah,' '            ; assume this is the break char
  2140.     cmp    byte ptr [si],'{'    ; field starts with brace?
  2141.     jne    genup11            ; ne = no
  2142.     mov    ah,'}'            ; use this break char
  2143.     inc    si            ; skip over leading brace
  2144.     dec    cx            ; one less char to consider
  2145. genup11:lodsb                ; get a char
  2146.     cmp    al,ah            ; break char yet?
  2147.     je    genup12            ; e = yes
  2148.     or    al,al            ; end of text?
  2149.     jz    genup12            ; z = yes
  2150.     stosb                ; store char without leading padding
  2151.     inc    byte ptr [bx]        ; count chars stored in this field
  2152.     loop    genup11            ; continue
  2153. genup12:mov    bx,di            ; where to store next count byte
  2154.     mov    byte ptr [di],0        ; null terminator
  2155.     ret
  2156. genupwd    endp
  2157.     
  2158. ; Send    "I" packet with transmission parameters
  2159.  
  2160. IPACK    PROC    NEAR
  2161.     call    serini            ; initialize serial port
  2162.     jnc    ipack1
  2163.     ret                ; c = failure
  2164. ipack1:    call    clrbuf            ; clear serial port buffer
  2165.     call    ihostr            ; initialize the host
  2166.     call    sparmax            ; set up our maximum capabilites
  2167.     mov    trans.windo,1        ; no windows yet
  2168.     call    makebuf            ; remake buffers
  2169.     xor    ax,ax
  2170.     mov    rpacket.numtry,al    ; number of receive retries
  2171.     mov    fsta.pretry,ax        ; no retries
  2172.     mov    pktnum,al        ; packet number 0
  2173.     mov    windlow,al        ; reset windowing
  2174.     call    packlen            ; compute packet length
  2175.     call    getbuf            ; get buffer for sending
  2176.     call    rpar            ; store them in the packet
  2177.     mov    trans.chklen,1        ; one char for server function
  2178.     mov    [si].pktype,'I'        ; "I" packet
  2179.     call    sndpak            ; send the packet
  2180.     jnc    ipack2            ; nc = success
  2181.     ret                ; return failure
  2182. ipack2:    mov    al,[si].seqnum
  2183.     mov    ah,maxtry        ; retry threshold
  2184.     add    ah,ah
  2185.     add    ah,maxtry        ; triple the normal retries
  2186.     mov    chkparflg,1        ; check for unexpected parity
  2187.     call    response        ; get response
  2188.     jnc    ipack3            ; nc = success
  2189.     call    bufclr            ; clear all
  2190.     cmp    rpacket.pktype,'E'    ; was it an Error pkt response?
  2191.     je    ipack4            ; e = yes, this is forgivable
  2192.     stc                ; carry set for failure
  2193.     ret                ; return failure
  2194.  
  2195. ipack3:    cmp    rpacket.pktype,'Y'    ; ACK response?
  2196.     jne    ipack4            ; ne = no
  2197.     push    si
  2198.     mov    si,offset rpacket    ; packet address
  2199.     call    spar            ; read in the data
  2200.     pop    si
  2201.     call    packlen            ; get max send packet size
  2202.     call    makebuf            ; remake buffers for new windowing
  2203. ipack4:    cmp    rpacket.pktype,'E'    ; was it an Error pkt response?
  2204.     jne    ipack5            ; ne = no
  2205.     mov    dx,offset emptymsg    ; clear last error line
  2206.     call    ermsg            ; do it
  2207. ipack5:    clc
  2208.     ret                ; return success
  2209. IPACK    ENDP
  2210.  
  2211. ; Returns BX the updated pointer to the input buffer
  2212. ;      input buffer = <ascii data length count byte>textstring
  2213. ; return carry clear if have text, else carry set for none
  2214. INPUT    PROC    NEAR
  2215.     mov    temp2,bx        ; where to put byte count
  2216.     inc    bx            ; start text after count byte
  2217.     xor    dx,dx            ; help, none
  2218.     mov    ah,cmline        ; get text with embedded whitespace
  2219.     call    comnd
  2220.     jnc    input1            ; nc = success
  2221.     mov    bx,temp2        ; empty field, restore pointer
  2222.     ret                ; failure
  2223. input1:    push    bx
  2224.     mov    bx,temp2
  2225.     add    al,' '            ; convert byte count to ascii
  2226.     mov    [bx],al            ; store count byte
  2227.     pop    bx            ; return pointer to next free byte
  2228.     clc                ; say have bytes
  2229.     ret
  2230. INPUT    ENDP
  2231.  
  2232. code    ends
  2233.     end
  2234.